2012-02-22 13 views
5

Necesito hash contra una variable miembro en lugar de la clase, por lo que no compruebo si la referencia está en el diccionario. Sin anular los valores predeterminados, no encontrará un Value idéntico, pero solo devolverá si encuentra la misma instancia exacta de HashedType, de modo que este código falla.Ventaja de derivar la clase externa de IEqualityComparer <> sobre la anulación GetHashCode e Igual

Dictionary.Add(new HashedType(4)); 
Dictionary.Contains(new HashedType(4)); // fails to find 4 

Definición de HashedType:

HashedType 
{ 
    public HashedType(Int32 value) { Value = value); } 
    public HashedType(String value) { Value = value); } 
    public object Value; 
    public void Serialize(Serializer s) 
    { 
     if (Value.GetType() == typeof(Int32)) 
     { 
     s.Set<Int32>(0); 
     s.Set<Int32>(Value); 
     } 
     else 
     { 
     s.Set<Int32>(1); 
     s.Set<String>(Value); 
     } 

    } 
} 

Parece que puedo reemplazar GetHashCode() y equals() para hacer esto por mí.

Sin embargo, MSDN recomienda que cree una clase separada que proceda de IEqualityComparer y crear instancias de mis diccionarios utilizando HashedType con HashedTypeComparer: IEqualityComparer.

para ayudar a hacer esto más fácil, he derivado de diccionario y creé

HashedTypeDictionary<U> : Dictionary<T,U> 
{ 
    public HashedTypeDictionary() : base(new HashedTypeComparer()) { } 
    public bool Equals(HashedType a, HashedType b) { return a.Value == b.Value; } 
    publci int GetHashCode(HashedType a) { return a.Value.GetHashCode(); } 
} 

todo esto parece artificial.

¿La única ventaja que obtengo es que no cambie Equals()?

Quiero decir, realmente hablando, me gustaría que Equals se compare contra ese único miembro de todos modos.

Respuesta

4

La idea es que object.Equals es la igualdad natural para ese tipo (y GetHashCode debe coincidir con esa idea de igualdad). IEqualityComparer se usa cuando desea una igualdad diferente caso por caso.

Considere por ejemplo, un string. Los métodos reemplazados Equals & GetHashCode hacen comparaciones entre mayúsculas y minúsculas. Pero, ¿y si quieres un diccionario donde las teclas no distingan entre mayúsculas y minúsculas? Usted escribe un IEqualityComparer que no distingue entre mayúsculas y minúsculas y lo pasa en el constructor del diccionario.

Sus ejemplos suenan como si dos instancias de HashedType se trataran normalmente como iguales si sus miembros son iguales. En ese caso, recomendaría anular los métodos object.Equals y object.GetHashCode y no escribir un IEqualityComparer.

3

El motivo por el que elegiría uno sobre el otro es si siempre quiere que las instancias de un tipo determinado se comparen usando una cierta lógica, o solo en esta situación.

Equals y GetHashCode proporcionan la implementación "verdadera" de si dos objetos son lógicamente iguales. IEqualityComparer le permite anular eso en una base de caso caso por caso, y separar la propiedad (pueden ser diferentes las partes que controlan las entidades frente al código que las usa).

0

Si la mayoría de las veces desea que el comportamiento del diccionario funcione de manera predeterminada, anule GetHashCode e Igual. Tenga en cuenta que para que esto funcione nunca deben cambiar durante el ciclo de vida del objeto, por lo tanto, si están ejecutando Value, entonces Value debe establecerse en el constructor y una propiedad de solo lectura.

IEqualityComparer se utiliza realmente para cuando quiere comparar cosas de manera diferente en una sección de su programa.

2

Imagine, por un momento, que no posee la clase subyacente (es decir, es producida por otro equipo, o solo se le ha dado como un binario). Usted siempre puede crear el IEqualityComparer. Es posible que no tenga la opción de cambiar Equals y GetHashCode ...

Cuestiones relacionadas