2010-09-21 9 views
7

necesito comparar dos objetos pero comparar varias de sus propiedades en un solo golpe. esto no es para ordenar, sino para confirmar si algo ha cambiado; como uno es la instancia guardada anterior, y la segunda es una instancia recién importada de la misma cosacomprobando dos instancias de objeto para ver si son las mismas

supongo que esto se logra mejor escribiendo un comparador personalizado. Estoy un poco confundido sobre si hacer IComparer, o IComparable, o qué tbh.

gracias

nat

+1

Esa es una buena pregunta. Todas las diferentes comparaciones me confunden también. – Greg

Respuesta

8

Si solo tiene una definición única de igualdad para su clase, realmente no necesita implementar ninguna interfaz: simplemente anule el método Equals. Sin embargo, la mejor práctica sería implementar IEquatable<T> y anular GetHashCode con sensatez (si no anula el código hash, la igualdad se comportará mal cuando las clases de recopilación, los métodos LINQ, etc., lo utilicen como condición previa para la igualdad). He aquí un ejemplo de implementación:

public class Person : IEquatable<Person> 
{ 
    public string Name { get; set; } 
    public int Age { get; set; } 

    public override int GetHashCode() 
    { 
     return (Name == null ? 0 : Name.GetHashCode())^Age; 
    } 

    public override bool Equals(object obj) 
    { 
     return Equals(obj as Person); 
    } 

    public bool Equals(Person other) 
    { 
     return other != null && other.Name == Name && other.Age == Age; 
    } 
} 

Esto le permitirá hacer:

Person savedPerson = ... 
Person importedPerson = ... 

bool hasChanged = !savedPerson.Equals(importedPerson); 

Si, por el contrario, usted tiene un montón de diferentes definiciones de la igualdad para diferentes circunstancias, su La mejor opción sería escribir diferentes implementaciones de IEqualityComparer<T>. He aquí un ejemplo de implementación:

public class AgeComparer : IEqualityComparer<Person> 
{ 
    public bool Equals(Person x, Person y) 
    { 
     return (x == null || y == null) ? x == y : x.Age == y.Age; 
    } 

    public int GetHashCode(Person obj) 
    { 
     return obj == null ? 0 : obj.Age; 
    } 
} 

En este caso, el cheque se verá así:

Person savedPerson = ... 
Person importedPerson = ... 
IEqualityComparer<Person> comparer = ... 

bool hasChanged = !comparer.Equals(savedPerson, importedPerson); 
+0

¿En qué se diferencia el IEquatable Igual a los iguales definidos en Object? – Greg

+0

parece que es el IEqualityComparer para mí en este caso, ya que necesito verificar una serie de propiedades de mi person.ie.managerID, phoneNumber, ubicación ... etc. y si alguno de ellos ha cambiado, necesito la comparación para devolver el resultado. .. a menos que me esté perdiendo algo? pero tal vez no entiendo lo que hace gethashcode .. – nat

+0

@nat: Sí, exactamente. – Ani

0

Sí tendrá que tener su tipo de implementar IComparable. Here es una muestra de cómo hacerlo.

+7

Su enlace apunta a este hilo. Ese es un ejemplo de recursión, no IComparable;) – Marc

+1

lol @Marc. Gran captura. –

+0

Quizás quiso vincular: http://support.microsoft.com/kb/320727 –

0

Como se ha aludido a IComparable se utiliza normalmente para la clasificación.

En este caso usted quiere sobrecargar el operador de comparación: ==

Debido a que la comparación inversa también debe ser válido, esto implica también debe sobrecargar el operador =!.

Cuando sobrecarga == y! - también se espera que anule Equals y GetHashCode.

Un libro decente de C# debería explicar los detalles.

0

Una alternativa para implementar la interfaz IComparable sería anular las funciones Equals y GetHashCode.

0

Esa es la forma en que desea realizar la operación de comparación. Puede realizar la operación de las dos maneras:

public void Method() 
{ 
    Foo p1 = new Foo(); 
    Foo p2 = new Foo(); 

    p1.CompareTo(p2); 
    FooComparer c = new FooComparer(); 
    c.Compare(p1, p2); 
} 

class Foo : IComparable 
{ 
    public int CompareTo(object obj) 
    { 
     throw new NotImplementedException(); 
    } 
} 

class FooComparer : IComparer<Foo> 
{ 
    public int Compare(Foo x, Foo y) 
    { 
     throw new NotImplementedException(); 
    } 
} 

Prefiero usar IComparer como una separación de preocupaciones. Foo es mi clase, tengo algunas necesidades en ella. Si quiero comparar algunos Foos, uso FooComparer. Para su situación, puede devolver el número de propiedades modificadas desde el método Comparar. Si el método Compare devuelve 0. Entonces dos Foos son iguales.

Como dije. Así es como quieres realizar la acción, creo. Ignorar a los operadores de igualdad también es una buena solución. La implementación de IEqualityComparer<T> es otra solución.

Cuestiones relacionadas