/ / Equals vs GetHashCode cuando se comparan objetos: .net, comparación, es igual a, gethashcode

Equals vs GetHashCode cuando se comparan objetos: .net, comparación, es igual a, gethashcode

¿Debemos anular ambos Equals y GetHashCode propiedades al implementar una comparación de instancias de clase personalizada?

En el siguiente código tengo una colección de clases. La clase A es comparado por el ID, la clase B - por Code.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;

namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
List<I> bars = new List<I>();
bars.Add(new A() { Id = 1, Code = "one A" });
bars.Add(new B() { Id = 1, Code = "one B" });
bars.Add(new A() { Id = 1, Code = "one A+" });
bars.Add(new B() { Id = 1, Code = "one B" }); // Code = "one B+"

var distictBars = bars.Distinct();

foreach (var item in distictBars)
{
Debug.WriteLine(item.Code);
}
}
}

interface I
{
string Code { get; set; }
}

class A : I, IEquatable<A>
{
public int Id { get; set; }
public string Code { get; set; }

public bool Equals(A other)
{
// this is the ??? comparison
return this.Id == other.Id;
//return this.Code == other.Code;
}

public override bool Equals(object obj)
{
if (obj is A)
return this.Equals(obj as A);
else
return object.ReferenceEquals(this, obj);
}

public override int GetHashCode()
{
// this is the wanted comparison
return this.Id;
}
}

class B : I, IEquatable<B>
{
public int Id { get; set; }
public string Code { get; set; }

public bool Equals(B other)
{
// this is the ??? comparison
return this.Id == other.Id;
}

public override bool Equals(object obj)
{
if (obj is B)
return this.Equals(obj as B);
else
return object.ReferenceEquals(this, obj);
}

public override int GetHashCode()
{
// this is the wanted comparison
return this.Code.GetHashCode();
}
}
}

El resultado es:

one A
one B

en caso de que el comentado Code = "one B+" la salida es

one A
one B
one B+

Ahora me pregunto para qué debo anular el Equals en el B ¿Clase si parece que esto no tiene efecto en la comparación?

Es GetHasCode() ¿Anular lo suficiente para ese tipo de comparaciones?

Respuestas

13 para la respuesta № 1

Esto es lo que necesita entender acerca de la relación entre Equals y GetHashCode.

Los códigos hash utilizan las tablas hash para encontrar rápidamente un "grupo" en el que se espera que exista un elemento. Si los elementos están en dos cubos diferentes, se supone que no pueden ser iguales.

El resultado de esto es que debe ver un código hash, con el fin de determinar la singularidad, como un rápido negativo compruebe: es decir, si dos objetos tienen códigos hash diferentes, son no lo mismo (independientemente de cuál sea su Equals métodos de retorno).

Si dos objetos tienen la mismo código hash, residirán en el mismo cubo de una tabla hash. Entonces su Equals Se llamarán métodos para determinar la igualdad.

Asi que GetHashCode debe devuelve el mismo valor para dos objetos que quieras que sean considerados iguales.


4 para la respuesta № 2

Siempre hay que anularlos. juntos y con implementaciones compatibles. Un medio de coincidencia / desajuste de código hash (respectivamente) "posible igualdad "y" no igualdad ". El código hash por sí mismo No indica igualdad. Por lo tanto, después de que se encuentra una coincidencia de código hash (o se utiliza para crear grupos de valores), Equals Todavía se comprueba para determinar una coincidencia.

Si los dos no están de acuerdo, es posible que nunca encuentres coincidencias.


4 para la respuesta № 3

los Distinct método utilizará el GetHashCode método para determinar la desigualdad entre los ítems, y la Equals Método para determinar la igualdad.

Primero haga una comparación rápida usando el hashel código para determinar qué elementos definitivamente no son iguales, es decir, tienen diferentes códigos hash, luego compara los elementos que tienen el mismo código hash para determinar cuáles son realmente iguales.

En su implementación de la B clase tiene una implementación inconsistente de la GetHashCode y Equals método, por lo que la comparación no funcionará correctamente. Sus dos B los objetos tienen diferentes códigos hash, por lo que no se pueden comparar entre sí. Dos elementos que se consideran iguales también deben devolver el mismo código hash.

Si una clase implementa el IEquatable<T> interfaz, la Equals(T) método será utilizado, de lo contrario el Equals(object) Se utiliza el método.