2009-07-22 13 views
9

¿Cuál es la mejor manera de crear su propio método GetHashCode para una clase en C#? Supongamos que tengo una clase simple (que reemplaza el método Equals), de la siguiente manera:Creando el método GetHashCode en C#

class Test 
    { 
     public string[] names; 

     public double[] values; 

     public override bool Equals(object obj) 
     { 
     return (obj is Test) && this.Equals((Test)obj); 
     } 

     public bool Equals(Test t) 
     { 
     return names.Equals(t.names) && values.Equals(t.values); 
     } 
    } 

¿Debo utilizar el código predeterminado para el método GetHashCode?

public override int GetHashCode() 
    { 
    return base.GetHashCode(); 
    } 

¿Debo basar el método en los contenidos de mi clase?

public override int GetHashCode() 
    { 
    return names.GetHashCode() + values.GetHashCode() ; 
    } 

¿O debería hacer algo más?

+0

Usted no está anulando es igual aquí. – jjnguy

+0

En realidad, creo que conducirá a stackoverflow. – jjnguy

+0

No, no desbordará la pila. Sin embargo, tampoco funcionará. – SLaks

Respuesta

12

System.Array no reemplaza GetHashCode o Equals, por lo que utilizan igualdad de referencia. Por lo tanto, no deberías llamarlos.

Para implementar GetHashCode, vea this question.

Para implementar Equals, utilice el método de extensión SequenceEqual.

EDITAR: En .Net 2.0, usted tiene que escribir su propia versión de SequenceEqual, así:

public static bool SequenceEquals<T>(IList<T> first, IList<T> second) { 
    if (first == second) return true; 
    if (first == null || second == null) return false; 

    if (first.Count != second.Count) return false; 

    for (int i = 0; i < first.Count; i++) 
     if (!first[i].Equals(second[i])) 
      return false; 

    return true; 
} 

Se puede escribir que tomar IEnumerable<T> en lugar de IList<T>, pero sería sea ​​un poco más lento porque no podrá salir temprano si los parámetros tienen diferentes tamaños.

+0

Gracias por la excelente y rápida respuesta. ¿Hay alguna alternativa a SequenceEqual que funcione con .NET framework 2.0? –

2

Es muy importante asegurarse de mantener la anulación de .GetHashCode() en el paso con .Equals().

Básicamente, usted debe asegurarse de que consideran los mismos campos a fin de no violar la primera de las tres reglas de GetHashCode (de MSDN object.GetHashCode())

Si dos objetos resultan ser iguales, el método GetHashCode para cada objeto debe devolver el mismo valor. Sin embargo, si dos objetos no se comparan como iguales, los métodos GetHashCode para el objeto dos no tienen que devolver valores diferentes.

En otras palabras, debe asegurarse de que cada vez que .Equals considere dos instancias iguales, también tendrán el mismo .GetHashCode().

Según lo mencionado por otra persona aquí, this question detalla una buena implementación. En caso de que esté interesado, escribí algunos artículos de blog sobre la investigación de códigos hash a principios del año pasado. Puede encontrar mis divagaciones here (la primera entrada del blog que escribí sobre el tema)

1

Hay una buena discusión de los temas here, y la actualización más reciente se refiere a la BaseObject abstract class proporcionada por SharpArchitecture.

Si quiere algo más ad hoc, he encontrado que el código que ReSharper genera para Equals() y GetHashCode() está bien.