2010-10-12 13 views
5

Me he preguntado sobre esto, así que supongo que lo preguntaré.GetHashCode Equality

mayoría de los lugares que verá utilizar la misma lógica semántica para primordial es igual a como GetHashCode por la igualdad miembro por miembro ... sin embargo, suelen utilizar diferentes implementaciones:

public override bool Equals(object obj) 
    { 
     if (obj == null || GetType() != obj.GetType()) 
     { 
      return false; 
     } 
     var other = (MyType)obj; 
     if (other.Prop1 != Prop1) 
     { 
      return false; 
     } 
     return true; 
    } 

    public override int GetHashCode() 
    { 
     int hash = -657803396; 
     num ^= Prop1.GetHashCode(); 
     return num; 
    } 

Si va a aplicar la igualdad miembro por miembro para su tipo (digamos para almacenar en un diccionario), ¿por qué no anula GetHashCode luego hacer algo como esto para iguala a:

public override bool Equals(object obj) 
    { 
     return this.HashEqualsAndIsSameType(obj); 
    } 

    public static bool HashEquals(this object source, object obj) 
    { 
     if (source != null && obj != null) 
     { 
      return source.GetHashCode() == obj.GetHashCode(); 
     } 
     if (source != null || obj != null) 
     { 
      return false; 
     } 
     return true; 
    } 

    public static bool HashEqualsAndIsSameType<T>(this T source, object obj) 
    { 
     return (obj == null || obj.GetType() == typeof(T)) && source.HashEquals(obj); 
    } 

Respuesta

10

Porque hay es un riesgo real de conflictos. Los códigos Hash son no únicos. Pueden (cuando son diferentes) probar la desigualdad, pero nunca la igualdad. En la búsqueda de un artículo:

  • obtener el hash-código (s)
  • si el hash-código es diferente, el objeto es diferente; descartarlo
  • si el hash-código es el mismo, cheque es igual a:
  • si Igual informes true que son la misma cosa
  • descarta

Considere long ... desde hash código es int , es fácil ver que hay muchos y muchos conflictos.

+0

Entonces, ¿cómo recomendaría la implementación de GetHashCode/Equals para miembros con la menor cantidad de referencias de miembros duplicados? Tales duplicaciones pueden conducir a omisiones accidentales y causar problemas significativos (que es lo que provocó mi pregunta hoy). Además, ¿qué sucede si queremos una suma de comprobación única para un objeto? ¿Existe una buena interfaz que ya existe para definir que un tipo ofrece la capacidad de calcular una suma de comprobación? – Jeff

+0

@jeff es muy raro que lo necesite, pero las herramientas como resharper lo harán por usted –

+0

Un ejemplo: almacenamiento en caché optimista sin conexión y/o bloqueo de objetos de varios tipos (en otras palabras, no hay columna en una tabla en un base de datos para etiquetar con una identificación de versión). Tanto el cliente como el servidor necesitan una forma de calcular un hash o una suma de comprobación (como lo llamaría) que es única, de modo que si el cliente devuelve una versión obsoleta al servidor, el servidor sabe que no debe guardarla y lanzar un excepción. ¿Cómo calcularía el hash/checksum para este propósito? – Jeff

1

los valores hash no son 1-a-1, puede tener varios valores diferentes que los hash para el mismo valor, pero que debería com pare como no igual. Entonces realmente no puedes implementar Equals en términos de GetHashCode. Esta es la razón por la que tiene colisiones en una tabla hash, y por qué una búsqueda en tabla hash debe involucrar llamadas a GetHashCode e Igual.