EqualityComparer & lt; T & gt; .Default vs. T.Equals
Angenommen, ich habe eine generische MyClass<T>
muss zum vergleichen von zwei Objekten des Typs <T>
. Normalerweise würde ich so etwas tun ...
void DoSomething(T o1, T o2)
{
if(o1.Equals(o2))
{
...
}
}
Nehmen wir nun an meine MyClass<T>
hat einen Konstruktor, der unterstützt das übergeben eines benutzerdefinierten IEqualityComparer<T>
ähnlich Dictionary<T>
. In diesem Fall würde ich tun müssen ...
private IEqualityComparer<T> _comparer;
public MyClass() {}
public MyClass(IEqualityComparer<T> comparer)
{
_comparer = comparer;
}
void DoSomething(T o1, T o2)
{
if((_comparer != null && _comparer.Equals(o1, o2)) || (o1.Equals(o2)))
{
...
}
}
Entfernen diese lange if-Anweisung, es wäre gut, wenn ich könnte _comparer
standardmäßig ein 'Standard-Programm', wenn die normalen Konstruktor verwendet wird. Ich suchte nach etwas, wie typeof(T).GetDefaultComparer()
aber nicht in der Lage war zu finden, alles wie es.
Habe ich EqualityComparer<T>.Default
könnte ich nutzen? Und würde dann dieses snippet ...
public MyClass()
{
_comparer = EqualityComparer<T>.Default;
}
void DoSomething(T o1, T o2)
{
if(_comparer.Equals(o1, o2))
{
...
}
}
... liefern die gleichen Ergebnisse wie die Verwendung o1.Equals(o2)
für alle möglichen Fälle?
(Wie sehen a side note, würde es bedeuten, ich würde auch brauchen, um irgendwelche spezielle generische Einschränkung für <T>
?)
InformationsquelleAutor der Frage takrl | 2011-05-02
Du musst angemeldet sein, um einen Kommentar abzugeben.
Es sollten die gleichen sein, aber es ist nicht garantiert, denn Sie hängt von details der Implementierung der Typ
T
.Erklärung:
Ohne eine Einschränkung zu
T
, o1.Equals(o2) ruftObject.Equals
, auch wennT
implementiertIEquatable<T>
.EqualityComparer<T>.Default
jedochObject.Equals
nur, wennT
nicht umsetzenIEquatable<T>
. Wenn es hat implementieren, die Schnittstelle, verwendet esIEquatable<T>.Equals
.Solange
T
's Umsetzung vonObject.Equals
nur AnrufeIEquatable<T>.Equals
das Ergebnis ist das gleiche. Aber das folgende Beispiel, das Ergebnis ist nicht das gleiche:Nun, es macht keinen Sinn, implementieren Sie eine Klasse wie dieses. Aber Sie haben das gleiche problem, wenn die Durchführung der
MyObject
einfach vergessen, Sie zu überschreibenObject.Equals
.Fazit:
Mit
EqualityComparer<T>.Default
ist ein guter Weg zu gehen, weil Sie nicht brauchen, um Unterstützung buggy-Objekte!InformationsquelleAutor der Antwort Daniel Hilgarth
Standardmäßig bis überschreiben in einer Klasse
Object.Equals(a,b)
/a.Equals(b)
führt einen Vergleich von Referenz.Was comparer zurückgegeben werden, indem
EqualityComparer<T>.Default
hängtT
. Zum Beispiel, wennT : IEquatable<>
dann die entsprechendenEqualityComparer<T>
erstellt werden.InformationsquelleAutor der Antwort abatishchev
Könnten Sie die null-coaelescense Betreiber ?? zu verkürzen, die, wenn es wirklich wichtig ist
InformationsquelleAutor der Antwort Marino Šimić
Ja, ich denke, es wäre sinnvoll, die
EqualityComparer<T>.Default
denn er nutzt die Umsetzung vonIEquatable<T>
wenn der TypT
implementiert, oder das überschreiben vonObject.Equals
sonst. Sie könnten das wie folgt:InformationsquelleAutor der Antwort AbdouMoumen
Das ist genau das, was
Dictionary<>
und andere generische Sammlungen in der BCL tun, wenn Sie nicht geben Sie einen comparer bei der Konstruktion des Objekts. Der Vorteil dabei ist, dassEqualityComparer<T>.Default
wird wieder das richtige Programm fürIEquatable<T>
- Typen nullable-Typen und enums. Wenn T ist keiner von denen, die es tun, ein einfaches ist-Gleich-Vergleich, wie man alten code macht.InformationsquelleAutor der Antwort Ryan Hauert