Tengo una clase compleja en mi proyecto C# en la que quiero poder hacer pruebas de igualdad. No es una clase trivial; contiene una variedad de propiedades escalares así como referencias a otros objetos y colecciones (por ejemplo, IDictionary). Por lo que vale, mi clase está sellada.Reemplazando el método de instancia Object.Equals() en C#; ahora Code Analysis/FxCop warning CA2218: "también debería redefinir GetHashCode". ¿Debo suprimir esto?
Para habilitar una optimización del rendimiento en otro lugar de mi sistema (una optimización que evita costosos viajes redondos de red), necesito poder comparar instancias de estos objetos entre sí para la igualdad – que no sea la referencia incorporada igualdad – y por lo tanto estoy anulando el método de instancia Object.Equals(). Sin embargo, ahora que lo he hecho, Visual Studio Análisis de código de 2008 también conocido como FxCop, que sigo activado por defecto, está levantando la siguiente advertencia:
advertencia: CA2218: Microsoft.Usage: Desde 'MySuperDuperClass' redefine Equals, también debería redefinir GetHashCode.
Creo que entiendo la razón de esta advertencia:Si Voy a utilizar este tipo de objetos como el clave en una colección, el código hash es importante. es decir, see this question. Sin embargo, no voy a utilizar estos objetos como la clave de una colección. Nunca.
sentimiento justificado suprimir la advertencia, miré hacia arriba code CA2218 in the MSDN documentation para obtener el nombre completo de la advertencia así que podría aplicar un atributo SuppressMessage
a mi clase de la siguiente manera:
[SuppressMessage("Microsoft.Naming",
"CA2218:OverrideGetHashCodeOnOverridingEquals",
Justification="This class is not to be used as key in a hashtable.")]
Sin embargo, al leer más, me di cuenta de lo siguiente:
Cómo arreglar Violaciónes
Para corregir una infracción de esta regla, proporciona una implementación de GetHashCode. Para un par de objetos de del mismo tipo, debe asegurarse de que la implementación devuelva el mismo valor si su implementación de Igual devuelve verdadero para el par.
Cuando para suprimir advertencias
----->No suprimir una advertencia de esta regla . [flecha & el énfasis es mío]
lo tanto, me gustaría saber: Por qué no debería suprimir esta advertencia ya que estaba planeando a? ¿Mi caso no garantiza la supresión? No quiero codificar una implementación de GetHashCode() para este objeto que nunca se llamará, ya que mi objeto nunca será la clave en una colección. Si quisiera ser pedante, en lugar de suprimir, ¿sería más razonable para mí anular GetHashCode() con una implementación que arroje una NotImplementedException?
Actualización: que sólo se veía este tema de nuevo en buen libro Effective C# de Bill Wagner, y se establece en "Punto 10: Entender los peligros de GetHashCode()":
Si' re definir un tipo que no se usará como clave en un contenedor , esto no tendrá importancia. Los tipos que representan controles de ventana, controles de página web o conexiones de base de datos es poco probable que se utilicen como claves en una colección . En esos casos, haga nada. Todos los tipos de referencia tendrán código hash que es correcto, incluso si es muy ineficiente. [...] En la mayoría de los tipos que cree, el mejor enfoque es evitar la existencia de GetHashCode() por completo.
... de ahí surgió originalmente la idea de que no debía preocuparme GetHashCode() siempre.
En realidad, compara casi todos los miembros de la clase para determinar la igualdad. La clase contiene suposiciones para una serie de cálculos. Cualquiera de ellos siendo diferente es suficiente para que considere los objetos diferentes. Algunas de las suposiciones son arreglos o colecciones de otros números. Así que GetHashCode sería necesariamente tan complejo si se implementara (correctamente). –
@Chris: No tiene que ser así. Una implementación simple pero a menudo aceptable es para XOR los valores GetHashCode de los miembros. –
Una implementación aún más simple y aceptable (pero no siempre óptima) es devolver el valor de GetHashCode() de un solo campo. Eso es lo que sucede para una estructura. –