2010-07-07 9 views
37

Mientras aprendí .net (por C#) encontré 5 formas de verificar la igualdad entre los objetos.5 maneras de verificar la igualdad en .net ... ¿por qué? y que usar?

  1. El método ReferenceEquals().
  2. El método virtual Equals(). (System.Object)
  3. El método static Equals().
  4. El método Equals de la interfaz IEquatable.
  5. El operador de comparación ==.

Mi pregunta es:

  1. por qué hay tantos método equals() junto con el operador de comparación?
  2. ¿Cuál de los Iguales virtuales() o los iguales de IEquatable ..() método sholud ser utilizado (por ejemplo, si usamos nuestras propias clases de colección)

Respuesta

26

1 - La referencia equivale a comprobar si dos variables de tipo de referencia (clases, no estructuras) se refieren a la misma dirección de memoria.

2 - El método virtual Equals() verifica si dos objetos son equivalentes.Digamos que usted tiene esta clase:

class TestClass{ 
    public int Property1{get;set} 
    public int Property2{get;set} 

    public override bool Equals(object obj) 
    { 
     if (obj.GetType() != typeof(TestClass)) 
      return false; 

     var convertedObj = (TestClass)obj; 

     return (convertedObj.Property1 == this.Property1 && convertedObj.Property2 == this.Property2); 
    } 
} 

y 2 objetos de esa clase:

var o1 = new TestClass{property1 = 1, property2 = 2} 
var o2 = new TestClass{property1 = 1, property2 = 2} 

aunque los dos objetos no son la misma instancia de TestClass, la llamada a o1.Equals (o2) volverá verdadero.

3 - El método estático Equals se usa para manejar problemas cuando hay un valor nulo en la verificación. imaginar esto, por ejemplo:

TestClass o1 = null; 
var o2 = new TestClass{property1 = 1, property2 = 2} 

Si intenta esto:

o1.Equals(o2); 

wil conseguir un NullReferenceException, porque los puntos O1 a nada. Para resolver este problema, haga esto:

Object.Equals (o1, o2);

Este método está preparado para manejar referencias nulas.

4 - La interfaz IEquatable es proporcionada por .Net por lo que no es necesario hacer moldes dentro de su método Equals. Si el compilador descubre que ha implementado la interfaz en una clase para el tipo que está tratando de verificar para la igualdad, otorgará prioridad a ese método sobre la anulación Object.Equals (Object). Por ejemplo:

class TestClass : IEquatable<TestClass> 
{ 
    public int Property1 { get; set; } 
    public int Property2 { get; set; } 

    public override bool Equals(object obj) 
    { 
     if (obj.GetType() != typeof(TestClass)) 
      return false; 

     var convertedObj = (TestClass)obj; 

     return (convertedObj.Property1 == this.Property1 && convertedObj.Property2 == this.Property2); 
    } 

    #region IEquatable<TestClass> Members 

    public bool Equals(TestClass other) 
    { 
     return (other.Property1 == this.Property1 && other.Property2 == this.Property2); 
    } 

    #endregion 
} 

ahora si hacemos esto:

var o1 = new TestClass{property1 = 1, property2 = 2} 
var o2 = new TestClass{property1 = 1, property2 = 2} 
o1.Equals(o2); 

El método llamado es iguala a (TestClass), antes de equals (Object).

5 - El operador == generalmente significa lo mismo que ReferenceEquals, verifica si dos variables apuntan a la misma dirección de memoria. El problema es que este operador puede ser anulado para realizar otros tipos de controles. En cadenas, por ejemplo, comprueba si dos instancias diferentes son equivalentes.

Este es un enlace muy útil para entender mejor las igualdades en .Net:

+0

Excelente. Los ejemplos realmente ayudan, pero hay un error tipográfico en su punto 4 donde el IEtabletable.Equals todavía usa 'convertedObj' – PaulG

+0

Gracias PaulG, ¡está arreglado ahora! =] – mverardo

29

Los ReferenceEquals().

Esto se utiliza para comprobar si dos variables dadas apuntan (las referencias de símbolo) al mismo objeto. Es literalmente equivalente a ((object)a) == ((object)b). Si anula el operador de comparación (==), entonces ReferenceEquals mantiene una forma de acceder al comportamiento predeterminado.

Sin embargo,, si se trata de un tipo de valor (por ejemplo, una estructura), este will always return false. Esto se debe a que los cuadros de comparación de cada tipo de valor a un nuevo objeto, por lo tanto, naturalmente, las referencias no serán iguales.


Los Iguales virtuales() método. (System.Object)

Esta es la manera predeterminada de comparar semánticamente dos objetos (de cualquier tipo). Cada clase anula esto como lo deseen. Por defecto es equivalente a una llamada CLR (InternalEquals) que básicamente compara las referencias de memoria.

Tenga en cuenta que si dos objetos devuelven verdadero para Equals() entonces GetHashCode() en cada uno de ellos must be equal. Sin embargo, si los códigos hash para dos objetos son de valor equivalente (es decir, obj1.GetHashCode() == obj2.GetHashCode()) esto significa , no significa que Equals() es verdadero.

Su clase normalmente debe implementar Equals y GetHashCode como un medio para distinguir instancias de clase, y debe implementar esto o el operador == (idealmente ambos) si es un tipo de valor.

Nota, para los tipos de valor el comportamiento por defecto es el de EqualsValueType.Equals() el que si nos fijamos en el reflector (o leer the MSDN description) utiliza la reflexión para comparar los miembros de las dos instancias de valor.


Los Iguales estáticos() método.

Esto es equivalente a return ((objA == objB) || (((objA != null) && (objB != null)) && objA.Equals(objB))) donde cada tipo se convierte en Object para la prueba. Mi prueba muestra que se ignoran los operadores de comparación sobrecargados, pero su método Equals se usará si los objetos no son nulos y no son la misma referencia. Como tal, a.Equals(b) no es necesariamente igual a object.Equals(a, b) (para los casos en que ((object)a) == ((object)b) o bien aob es nulo).


El método equals de interfaz IEquatable.

IEquatable proporciona una forma de tratar la comparación de instancias de la misma clase especialmente. Habiendo dicho que su Equals método should be handling the behaviour the same way:

Si implementa iguales, se debe también anula la clase base implementaciones de Object.equals (objeto) y GetHashCode por lo que su comportamiento es consistente con la de los IEquatable.Equals método

Nevertheless you should implement IEquatable:

Para hacer frente a la posibilidad de que los objetos de una clase serán almacenados en una matriz o un objeto de colección genérica, es una buena idea para poner en práctica IEquatable modo que el objeto puede ser fácilmente identificado y manipulado .


La comparación == operador

El operador de comparación de rendimientos por defecto cierto cuando ambos de sus objetos son la misma referencia.

Se is not recommended para anular el operador de comparación, a menos que se trata with a value type (en cuyo caso se recomienda, junto con el método Equals) o un tipo de referencia inmutable, que le suele comparar por valor (por ejemplo, string). Siempre implemente != al mismo tiempo (de hecho, recibo un error requires a matching operator '!=' to also be defined si no lo hago).


Recursos:

+2

excelente respuesta. +1 – RPM1984

0

Por primitivas, seguir con el operador ==.

En la mayoría de los objetos suministrados en .NET Framework y en cualquier objeto personalizado, cree el método .Equals() y el operador == solo comprobará si dos objetos hacen referencia al mismo objeto en el montón.

El propósito de la interfaz IEquatable es anular el método .Equals() para cambiar su comportamiento de la comprobación de la igualdad referencial para comprobar la igualdad de valores. El tipo System.String es un ejemplo de un objeto .NET incorporado que implementa esta interfaz.

El método .ReferenceEquals() proporciona una forma para que los desarrolladores que han anulado el método .Equals() estándar aún puedan verificar dos objetos para la igualdad referencial.

+2

"Primitivos"? Esto no es Java, mang! – Randolpho

1

Cada versión de igualdad es ligeramente diferente.

ReferenceEquals pruebas de igualdad de referencia.

virtual Equals comprueba de forma predeterminada la igualdad de referencia para los tipos de clase y la igualdad de valores para los tipos de estructura. Se puede anular para definir la igualdad de manera diferente, si se desea; y debe ser anulado para tipos de valores.

static Equals solo llama virtual Equals, pero también permite null argumentos.

IEquatable<T>.Equals es un equivalente genérico/tipo seguro para virtual Equals.

operator== está destinado a ser como el valor predeterminado virtual Equals, lo que significa igualdad de referencia para los tipos de clase (a menos que la clase también anule a otros operadores). También se debe anular para los tipos de valores.

Si escribe su propia clase de colección, use IEqualityComparer<T>, por defecto a EqualityComparer<T>.Default. No use ninguna de las comparaciones de igualdad directamente.

+0

thnx .. para resolver dudas sobre la implementación de nuestra propia clase de recopilación – Gaurav

Cuestiones relacionadas