UguaglianzaComparer .default fraintendinging?
-
11-12-2019 - |
Domanda
Ho una classe Person
, IT ATTUALMENTE equivale () Metodo da IEquatable<Person>
(Sostituisce anche il metodo Object.Equals
, consente di ignorare il metodo GetHashCode () per ora)
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;
}
}
.
OK, inizia:
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 };
.
Lascia parlare di questa linea:
bool b = lst1.SequenceEqual(lst2, EqualityComparer<Person>.Default);
.
Ho un problema Comprendere questa parte:
EqualityComparer<Person>.Default
.
Ho sentito che EqualityComparer<Person>.Default
controllerà se la classe implementerà IEquatable
- prenderà il metodo Equals(Person other)
e non il Equals(object obj)
. ha il vantaggio di evitare il boxe
Ma
Il Equals(Person other)
eseguirà con o senza EqualityComparer<Person>.Default
(perché è implementato i equiacking)
Allora di quale boxe stiamo parlando? Non c'è!
L'unica volta in cui Equals(object obj)
verrà eseguito è quando:
.
bool b = lst1.SequenceEqual(lst2,EqualityComparer<Object>.Default);
Ma Sono un programmatore! Non inviare mai un object
quando è in realtà un Person
!
Cosa mi manca? Ho difficoltà a capire il beneficio qui di EqualityComparer<Object>.Default
. Qualcuno può per favore darmi un esempio per dimostrarmi che mi sbaglio?
Soluzione
If you pass in null
as the second parameter or if you don't pass in a second argument at all (which is basically the same), the implementation of SequenceEquals will call EqualityComparer<T>.Default
itself (decompile Enumerable
to see this). That explains why you don't see a difference whether you provide EqualityComparer<T>.Default
or not.
So in the end the second parameter only makes sense if you want to use an equality comparer other than EqualityComparer<T>.Default
.
Altri suggerimenti
That you can pass in IEqualityComparer<object>.Default
is an effect of generic contravariance, added in .NET 4.
Essentially, an IEqualityComparer<BaseType>
can be used whenever an IEqualityComparer<DerivedType>
is required, where DerivedType : BaseType
. Since Person
derives from Object
, this means that an IEqualityComparer<Object>
can be used wherever an IEqualityComparer<Person>
is required.
The answer is here: http://msdn.microsoft.com/en-us/library/ms131187(v=vs.110).aspx
For a value type, you should always implement IEquatable and override Object.Equals(Object) for better performance. Object.Equals boxes value types and relies on reflection to compare two values for equality. Both your implementation of Equals and your override of Object.Equals should return consistent results.
If you do not override Equals and GetHashCode, EqualityComparer.Default actually takes care of that for you.