EqualityComparer<T>. ¿Malentendido predeterminado?
-
11-12-2019 - |
Pregunta
Tengo una clase Person
, implementa el método Equals() de IEquatable<Person>
(también anula Object.Equals
método, ignoremos el método GetHashcode() por ahora)
class Person : IEquatable<Person>
{
public string Name { get; set; }
public bool Equals(Person other)
{
return this.Name == other.Name;
}
public override bool Equals(object obj)
{
var person = obj as Person;
return person != null && person.Name == Name;
}
}
De acuerdo, empecemos:
Person p1 = new Person() { Name = "a" };
Person p2 = new Person() { Name = "a" };
List<Person> lst1 = new List<Person>() { p1 };
List<Person> lst2 = new List<Person>() { p2 };
Hablemos de esta línea:
bool b = lst1.SequenceEqual(lst2, EqualityComparer<Person>.Default);
Tengo un problema para entender esta parte:
EqualityComparer<Person>.Default
He oído que EqualityComparer<Person>.Default
comprobará si la clase está implementando IEquatable
- tomará el Equals(Person other)
Método y no el Equals(object obj)
. tiene la ventaja de evitar el boxeo
pero
el Equals(Person other)
correrá con o sin EqualityComparer<Person>.Default
(porque está implementando IEquatable)
Entonces, ¿de qué boxeo estamos hablando?¡no lo hay!
La única vez que Equals(object obj)
se ejecutará es cuando:
bool b = lst1.SequenceEqual(lst2,EqualityComparer<Object>.Default);
Pero ¡Soy programador!Nunca enviaré un object
cuando en realidad es un Person
!
¿Qué me estoy perdiendo?Tengo problemas para entender el beneficio aquí de EqualityComparer<Object>.Default
.¿Alguien puede darme un ejemplo para demostrar que estoy equivocado?
Solución
Si pasas null
como segundo parámetro o si no pasa ningún segundo argumento (que es básicamente lo mismo), la implementación de SequenceEquals llamará EqualityComparer<T>.Default
mismo (descompilar Enumerable
para ver esto).Eso explica por qué no ves una diferencia si proporcionas EqualityComparer<T>.Default
O no.
Entonces, al final, el segundo parámetro solo tiene sentido si quieres usar un comparador de igualdad. otro que EqualityComparer<T>.Default
.
Otros consejos
que puedes pasar IEqualityComparer<object>.Default
es un efecto de contravarianza genérica, agregado en .NET 4.
Esencialmente, un IEqualityComparer<BaseType>
se puede utilizar siempre que un IEqualityComparer<DerivedType>
es requerido, donde DerivedType : BaseType
.Desde Person
deriva de Object
, esto significa que un IEqualityComparer<Object>
se puede utilizar dondequiera que IEqualityComparer<Person>
se requiere.
La respuesta está aquí: http://msdn.microsoft.com/en-us/library/ms131187(v=vs.110).aspx
Para un tipo de valor, siempre debe implementar IEquatable y anular Object.Equals(Object) para obtener un mejor rendimiento.Object.Equals encuadra los tipos de valores y se basa en la reflexión para comparar la igualdad de dos valores.Tanto su implementación de Equals como su anulación de Object.Equals deberían arrojar resultados consistentes.
Si no anula Equals y GetHashCode, EqualityComparer.Default realmente se encarga de eso por usted.