EqualityComparer<T>.Default Missverständnis?
-
11-12-2019 - |
Frage
ich habe ein klasse Person
, implementiert es die Equals()-Methode von IEquatable<Person>
(überschreibt auch Object.Equals
Methode, ignorieren wir vorerst die GetHashcode()-Methode)
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;
}
}
In Ordnung, lass uns anfangen:
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 };
Reden wir über diese Zeile:
bool b = lst1.SequenceEqual(lst2, EqualityComparer<Person>.Default);
Ich habe ein Problem damit, diesen Teil zu verstehen:
EqualityComparer<Person>.Default
Das habe ich gehört EqualityComparer<Person>.Default
prüft, ob die Klasse implementiert wird IEquatable
- Es wird dauern Equals(Person other)
Methode und nicht die Equals(object obj)
. Es hat den Vorteil, dass Boxen vermieden wird
Aber
Die Equals(Person other)
werde rennen mit oder ohne EqualityComparer<Person>.Default
(weil es IEquatable implementiert)
Über welches Boxen reden wir also?Gibt es nicht!
Das einzige Mal, dass Equals(object obj)
wird ausgeführt, wenn:
bool b = lst1.SequenceEqual(lst2,EqualityComparer<Object>.Default);
Aber Ich bin Programmierer!Ich werde niemals eine senden object
wenn es tatsächlich ein Person
!
Was vermisse ich?Es fällt mir schwer, den Nutzen hiervon zu verstehen EqualityComparer<Object>.Default
.Kann mir bitte jemand ein Beispiel geben, um zu beweisen, dass ich falsch liege?
Lösung
Wenn du vorbeikommst null
als zweiten Parameter oder wenn Sie überhaupt kein zweites Argument übergeben (was im Grunde dasselbe ist), wird die Implementierung von SequenceEquals aufgerufen EqualityComparer<T>.Default
selbst (dekompilieren Enumerable
um das zu sehen).Das erklärt, warum Sie keinen Unterschied sehen, ob Sie etwas bereitstellen EqualityComparer<T>.Default
oder nicht.
Letztendlich macht der zweite Parameter also nur dann Sinn, wenn Sie einen Gleichheitsvergleicher verwenden möchten außer EqualityComparer<T>.Default
.
Andere Tipps
Dass du hineingehen kannst IEqualityComparer<object>.Default
ist eine Wirkung von generische Kontravarianz, hinzugefügt in .NET 4.
Im Wesentlichen ein IEqualityComparer<BaseType>
kann immer dann verwendet werden IEqualityComparer<DerivedType>
ist erforderlich, wo DerivedType : BaseType
.Seit Person
kommt von Object
, das bedeutet, dass ein IEqualityComparer<Object>
überall einsetzbar IEqualityComparer<Person>
ist erforderlich.
Die Antwort ist hier: http://msdn.microsoft.com/en-us/library/ms131187(v=vs.110).aspx
Für einen Werttyp sollten Sie für eine bessere Leistung immer IEquatable implementieren und Object.Equals(Object) überschreiben.Object.Equals fasst Werttypen zusammen und verwendet Reflektion, um zwei Werte auf Gleichheit zu vergleichen.Sowohl Ihre Implementierung von Equals als auch Ihre Überschreibung von Object.Equals sollten konsistente Ergebnisse liefern.
Wenn Sie Equals und GetHashCode nicht überschreiben, übernimmt EqualityComparer.Default dies tatsächlich für Sie.