Quiero que mi Food
clase pueda evaluar cuando sea igual a otra instancia de Food
. Más tarde lo usaré contra una Lista, y quiero usar su List.Contains()
método. ¿Debo implementar IEquatable<Food>
o simplemente anular Object.Equals()
? De MSDN:
Este método determina la igualdad mediante el uso del comparador de igualdad predeterminado, según lo definido por la implementación del objeto del método IEquatable.Equals para T (el tipo de valores en la lista).
Entonces mi siguiente pregunta es: ¿qué funciones / clases de .NET Framework utilizan Object.Equals()
? ¿Debo usarlo en primer lugar?
Respuestas:
La razón principal es el rendimiento. Cuando se introdujeron los genéricos en .NET 2.0 que fueron capaces de añadir un montón de clases ordenadas tales como
List<T>
,Dictionary<K,V>
,HashSet<T>
, etc. Estas estructuras hacen un uso intensivo deGetHashCode
yEquals
. Pero para los tipos de valor esto requería boxeo.IEquatable<T>
permite que una estructura implemente unEquals
método fuertemente tipado para que no se requiera boxeo. Por lo tanto, un rendimiento mucho mejor cuando se utilizan tipos de valor con colecciones genéricas.Los tipos de referencia no se benefician tanto, pero la
IEquatable<T>
implementación le permite evitar un reparto desde elSystem.Object
que puede marcar la diferencia si se llama con frecuencia.Sin embargo, como se señaló en el blog de Jared Parson , aún debe implementar las anulaciones de objetos.
fuente
IEquatable<T>
interfaz hace algo más que recordarle a un desarrollador que incluya unpublic bool Equals(T other)
miembro en la clase o estructura? La presencia o ausencia de la interfaz no hace ninguna diferencia en tiempo de ejecución. La sobrecarga deEquals
parece ser todo lo que es necesario.Según el MSDN :
Por lo tanto, parece que no hay una diferencia funcional real entre los dos, excepto que cualquiera podría llamarse dependiendo de cómo se use la clase. Desde el punto de vista del rendimiento, es mejor usar la versión genérica porque no hay penalización de boxeo / desempaquetado asociada con ella.
Desde un punto de vista lógico, también es mejor implementar la interfaz. Anular el objeto realmente no le dice a nadie que su clase es realmente equiparable. La anulación puede ser una clase de no hacer nada o una implementación superficial. El uso de la interfaz dice explícitamente: "¡Oye, esto es válido para la verificación de igualdad!" Es solo un mejor diseño.
fuente
Extendiendo lo que Josh dijo con un ejemplo práctico. +1 a Josh: estaba a punto de escribir lo mismo en mi respuesta.
De esta manera, tengo el método Equals () reutilizable que funciona de forma inmediata para todas mis clases derivadas.
fuente
Si llamamos
object.Equals
, obliga al costoso boxeo en los tipos de valor. Esto no es deseable en escenarios sensibles al rendimiento. La solución es usarIEquatable<T>
.La idea detrás
IEquatable<T>
es que da el mismo resultadoobject.Equals
pero más rápido. La restricciónwhere T : IEquatable<T>
debe usarse con tipos genéricos como a continuación.de lo contrario, se une a
slower object.Equals()
.fuente