2010-12-02 14 views
37

¿Es posible en C# comparar dos objetos de tipos desconocidos (incluidos los tipos de referencia y de valor) utilizando sus comparadores de tipo si existen?C# compare dos objetos de tipos desconocidos (incluidos los tipos de referencia y valor)

El objetivo es escribir una función que tendría una firma así:

public bool Compare(object a, object b) 
{ 
    // compare logic goes here 
} 

cual se devolvía

Compare(100d, 100d) == true 
Compare(100f, 100f) == true 
Compare("hello", "hello") == true 
Compare(null, null) == true 
Compare(100d, 101d) == false 
Compare(100f, null) == false 

// Use type comparators where possible, i.e.: 
Compare(new DateTime(2010, 12, 01), new DateTime(2010, 12, 01)) == true 
Compare(new DateTime(2010, 12, 01), new DateTime(2010, 12, 02)) == false 
Compare(new DateTime(2010, 12, 01), null) == false 

¿Hay un enfoque genérico para la solución de este problema que podría funcionar para cualquier tipo de objeto?

Respuesta

59

Se puede utilizar el método estático object.Equals(object x, object y) y no molestar a escribir su método en absoluto. Eso manejará los valores nulos apropiadamente, y delegará a una implementación de object.Equals(object) asociada con x o y ... no debería ser asunto que, como Equals, está destinado a ser simétrico.

Tenga en cuenta que este no utilizar los operadores == para cualquier tipo - los operadores no pueden ser anulados, solamente sobrecargados (lo que significa que son elegidos en tiempo de compilación , no ejecución en tiempo En la mayoría de los casos, Equals debe hacer lo que desee. En algunos casos, == puede no estar sobrecargado aunque Equals esté anulado ... pero nunca he sabido que lo contrario sea cierto en los tipos con los que he trabajado.

Tenga en cuenta que el uso de este enfoque cuadro cualquier tipo de valor ...

EDITAR: Sección eliminada sobre la reimplementación efectiva - mal - EqualityComparer<T>.Default. Vea la respuesta de Marc para más. Esto no te ayudará si no puedes usar un tipo genérico, por supuesto.

Un último punto: I no llamaría a su método Compare. Ese nombre generalmente se asocia con ordenando valores de en lugar de compararlos por igualdad.

+0

+1: Para una buena explicación, – TalentTuner

+1

+1 para esta y muchas otras respuestas del Sr. Skeet. ¡Gracias! –

+0

Seguramente, este último solo funcionará para los tipos de referencia, ya que tendrá que tener 'donde T: clase' para usar' v1 == null', por lo que evitará la comparación del tipo de valor. – aqwert

0

¿Qué hay de

if (a == null && b == null) return true; 
if (a == null && b != null) return false; 
return (a.equals(b)); 

?

5

¿Qué tal object.equals(x, y)? Esto también aceptará valores nulos.

-2

no estoy 100% seguro de si esto funciona en todos los casos, pero darle una oportunidad

 
public bool Compare(object a, object b) 
{ 
    return a.Equals(b); 
} 
+1

Esto causará una NullReferenceException si a es nulo. – Zeemee

20

Una opción razonable es es trabajar con los genéricos, es decir

public bool Compare<T>(T a, T b) {...} 

Usted no tendrá que especificar el T en su código, como el compilador generalmente será capaz de entenderlo (es decir,sus muestras existentes funcionarían "tal cual")

Para la ejecución:

bool equal = EqualityComparer<T>.Default.Equals(x, y); 

(para el tipo genérico de T)

pero realidad evitaría la palabra Compare, ya que es utilizado en otro lugar para significar </==/> - entonces podría tener:

public static bool Equals<T>(T a, T b) { 
    return EqualityComparer<T>.Default.Equals(a, b); 
} 

Este:

  • evita el boxeo cuando T es una estructura
  • maneja nulos/Nullable<T> correctamente
  • apoya IEquatable<T>
  • o cae de nuevo a normal Equals

lo hace no use el operador ==, pero MiscUtil tiene un Operator clase que se , a través de

bool equal = Operator.Equal<T>(x,y); 

(tenga en cuenta este último fallará si T no tiene un operador ==, aunque pensar en ello, podría utilizar EqualityComparer<T>.Default.Equals como punto de retorno; simplemente no lo hace)


Para completar, tenga en cuenta que Comparer<T>.Default.Compare(x,y) maneja operaciones de comparación.

+1

Gracias por la excelente respuesta, tanto las suyas como las respuestas de Jon Skeet funcionan para mi caso de uso particular. – Duane

Cuestiones relacionadas