2010-11-21 12 views
28

Como ya sabe, GetHashCode devuelve un valor semi exclusivo que se puede usar para identificar una instancia de objeto en una colección. Como buena práctica, se recomienda anular este método e implementar el suyo propio.Anulación de GetHashCode

Mi pregunta es: ¿anulas este método cuando trabajas en objetos personalizados? Si es así, ¿qué algoritmo utilizas para generar la identificación única?

Estaba pensando en generar un GUID y luego obtener datos enteros de ese identificador.

+2

tener una lectura de [esta cuestión] (http: // stackoverflow.com/questions/263400/what-is-the-best-algorithm-for-an-overridden-system-object-gethashcode) y sus respuestas. Describe una buena implementación del código hash. También hay una buena discusión sobre la superación de 'GetHashCode' para objetos mutables [aquí] (http://stackoverflow.com/questions/873654/overriding-gethashcode-for-mutable-objects-c). – adrianbanks

+7

No sé qué significa "semi-único" ... un valor es único o no lo es, y un código hash no es exclusivo. Por lo tanto, no le permite identificar un objeto en una lista. Y no es "una buena práctica" anular 'GetHashCode', es algo que hace cuando * necesita * (por ejemplo, para usar el objeto como clave en un diccionario), no porque crea que es una buena práctica. –

+0

Usar el objeto como clave se puede considerar como la identificación del objeto en una colección; es exactamente por eso que estoy buscando información sobre cuál es el mejor algoritmo para construir el identificador. A partir de identidades semi exclusivas: http://www.west-wind.com/Weblog/posts/4741.aspx –

Respuesta

24

Cuando se reemplaza GetHashCode() también es necesario para anular Equals(), operator== y operator!=. Y tenga mucho cuidado de cumplir con todos los requisitos para esos métodos.

Las pautas son here on MSDN. Cita más importante:

No es una buena idea anular el operador == en tipos no inmutables.

+0

Por lo que entiendo, eso no tendrá sentido porque, bueno, el objeto no cambiará su estado . –

+0

¿Qué no tiene sentido? –

+0

Anulando el operador ==. –

-2

Generalmente uso el GetHashCode agregado a partir de las propiedades del componente de la clase. P.ej.

public class Test 
{ 
    public string Text { get; set; } 
    public int Age { get; set; } 

    public override GetHashCode() 
    { 
    int result = 
     string.IsNullOrEmpty(Text) ? 0 : Text.GetHashCode() 
     + Age.GetHashCode(); 

    return result; 
    } 
} 
+5

Esta no es una buena manera de hacerlo, vea http://stackoverflow.com/questions/263400/what-is-the-best-algorithm-for-an-overridden-system-object-gethashcode –

+0

En general, agregando no es bueno para crear un código hash compuesto. Pero en este ejemplo específico no veo ningún problema con eso. Pero, por supuesto, el GetHashCode primordial sin anular Equals no tiene mucho sentido. – CodesInChaos

+0

¡Bueno, aprendes algo todos los días! –

1

En mi uso personal, solo anulo cuando la anulación es igual al método. En general, hago esto para los objetos que sé que podría ejecutar una consulta de LINQ to Objects, u otra operación de comparación.

Normalmente devuelvo, por ejemplo, un objeto LINQ to SQL entity u objeto DTO, el valor de la clave primaria. Cualquier cosa que devuelva, si no almacena el valor localmente, puede producir un resultado inesperado.

HTH.

0

solo tiene que anular GetHashCode si está reemplazando Equals. El tiempo de ejecución implementa el GetHashCode predeterminado de forma similar a como lo quería hacer: cada objeto tiene un campo oculto asignado por el tiempo de ejecución.

How to override GetHashCode

En realidad su IDE debe hacer esto para usted - cuando se escribe "reemplazar GetHashCode" el IDE debe generar este código repetitivo. Visual Studio no lo hace, pero SharpDevelop sí lo hace.

+0

La implementación predeterminada del método GetHashCode no garantiza valores de devolución únicos para diferentes objetos. En consecuencia, la implementación predeterminada de este método no se debe usar como un identificador de objeto único para propósitos de hash. De: http://msdn.microsoft.com/en-us/library/system.object.gethashcode.aspx – brain

+0

en VS, uno tiene que usar el fragmento 'igual' en su lugar – CodesInChaos

+1

@brain - Leí esto. ¿Significa que siempre debes anular GetHashCode cuando quieras almacenar tus objetos en un diccionario? No lo creo, casi nadie hace esto. La implementación predeterminada funciona bien para propósitos de Diccionario. No es perfecto, pero está bien: http://stackoverflow.com/questions/750947/net-unique-object-identifier –

1

Normalmente anularía los métodos hashcode y de comprobación de igualdad para las clases de datos (es decir, las clases en las que la semántica de los valores tiene sentido). Eche un vistazo a la pregunta this para una implementación común. Si anula Igualar código hash es igual. Usar un GUID es una idea bastante terrible porque quiere dos objetos que son instancias diferentes pero tienen el mismo valor para tener el mismo código hash y para que los iguales sean verdaderos.

27

Si usa el reajuste puede generar GetHashCode(), Equals y los cuerpos del método del operador para usted.

acceder a este menú pulsando Alt + Insertar.

http://www.jetbrains.com/resharper/webhelp/Code_Generation__Equality_Members.html

+1

http://www.jetbrains.com/resharper/webhelp/Code_Generation__Equality_Members.html – Deinonychus

+2

Una manera más fácil que no inserta tantas repeticiones, y se mantiene actualizado cuando la clase cambia: http: //eamonnerbonne.github .io/ValueUtils/ –

+0

Por la razón que sea alt + insert no abre mi menú de resharper, pero puedo usar el menú: Resharper -> Editar -> Generar código ... –