2010-03-19 16 views
30

Ich verstehe das einfach nicht - Was IEquatable kaufen Sie genau?Wann IEquatable verwenden und warum

Der einzige Grund, den ich es nützlich sehen kann, ist, wenn Sie einen generischen Typ erstellen und Benutzer zwingen, eine gute equals-Methode zu implementieren und zu schreiben.

Was bin ich

+1

Es sparen Sie Boxing/Unboxing Handhabung. Hier gute und einfache Erklärung dafür: http: //www.codeproject.com/Articles/20592/Implementing-IEquatable-Properly – Jviaches

Antwort

32

Vom MSDN:

Die IEquatable(T) Schnittstelle durch generische Sammlung verwendet wird, Objekte wie Dictionary(TKey, TValue), List(T) und LinkedList(T) wenn für die Gleichstellung in solchen Verfahren wie Contains Prüfung, IndexOf, LastIndexOf und Remove.

Die IEquatable<T> Implementierung wird eine weniger Besetzung für diese Klassen erfordern und als Ergebnis wird als die Standard-object.Equals Methode etwas schneller sein, die sonst verwendet werden würde. siehe als Beispiel die unterschiedliche Umsetzung der beiden Methoden:

public bool Equals(T other) 
{ 
    if (other == null) 
    return false; 

    return (this.Id == other.Id); 
} 

public override bool Equals(Object obj) 
{ 
    if (obj == null) 
    return false; 

    T tObj = obj as T; // The extra cast 
    if (tObj == null) 
    return false; 
    else 
    return this.Id == tObj.Id; 
} 
+3

Weiß jemand, was passiert, wenn Sie iequtalable nicht implementieren, wenn Sie generische Sammlungen verwenden? –

+1

@ChloeRadshaw wird dann eine Referenz für Referenztypen verwendet. – Cornelius

+1

Es wird mit den oben genannten Typen arbeiten, ohne IEquatable zu implementieren; Es wird stattdessen einfach die Standardeinstellung Equals() verwendet. Das heißt, es klingt wie IEquatable , wenn verfügbar, und vermeiden Sie das Boxen/Unboxing, Drew Freyling erwähnt. – Doug

11

Ich benutze IEquatable<T> ziemlich viel, wenn auch von einer rein technischen Sicht ist es nicht wirklich gibt Sie mir keine besonderen Vorteile. Überschreiben System.Object.Equals kann Ihnen die gleiche Funktionalität bieten.

Allerdings mag ich die Explizitheit der Implementierung IEquatable<T>. Ich benutze die Konzepte Entities und Wertobjekte von Domain-Driven Design eine ganze Menge, und verwenden Sie IEquatable<T> insbesondere für Wertobjekte, einfach weil es signalisiert, dass ein Typ gut definierte Gleichheit hat.

+7

Vergessen Sie nicht, dass die Verwendung von IEquatable bedeutet, dass Sie nicht mit dem Boxen/dulden müssen Unboxing, das Sie mit System.Object.Equals erhalten. –

+3

Nur versiegelte Typen sollten 'IEquatable 'implementieren. Wenn "IEquatable " etwas anderes als eine Kette zu "Object.Equals (Object)" tut, muss jeder abgeleitete Typ 'XDerived', der die Gleichheit neu definiert, 'IEquatable ' erneut implementieren und das Argument auf 'XDerived' setzen. Wenn dies nicht durchgeführt wird, würde dies zu einem Objekt führen, das sich z. a 'Wörterbuch '. – supercat

23

Ich bin erstaunt, dass der wichtigste Grund, die hier nicht erwähnt wird.

IEquatable<> wurde vor allem aus zwei Gründen für structs eingeführt:

  1. Für Werttypen (lesen structs) die nicht-generic Equals(object) Boxen erfordert. IEquatable<> lässt eine Struktur eine stark typisierte Equals Methode implementieren, so dass kein Boxen erforderlich ist.

  2. Für structs, die Standardimplementierung von Object.Equals(Object) (die in System.ValueType die überschriebene Version ist) eine Wertgleichheitsprüfung durch Reflexion über die Werte jedes Feld in der Art zu vergleichen. Wenn ein Implementierer die virtuelle Equals-Methode in einer Struktur überschreibt, besteht der Zweck darin, eine effizientere Methode zur Durchführung der Wertgleichheitsüberprüfung bereitzustellen und optional den Vergleich auf einer Teilmenge des Felds oder der Eigenschaften der Struktur zu basieren.

Beide verbessern die Leistung.

Referenztypen (Klassen lesen) profitieren nicht so sehr. Die IEquatable<> Implementierung lässt Sie eine Besetzung von System.Object vermeiden, aber das ist ein sehr trivialer Gewinn.Ich mag immer noch IEquatable<> für meine Klassen implementiert werden, da es logisch die Absicht explizit macht.

0

Weiter zu den anderen Antworten hier ist ein sehr guter Grund zu implementieren IEquatable<T> (und offensichtlich überschreiben Equals(object) auch) für Werttypen. Sehen Sie sich einfach den Standardcode ValueType.Equals(object) an, der sonst aufgerufen wird. Es ist ein absoluter Performance-Killer, der Boxing, Typevaluierung und schließlich Reflexion einleitet, wenn es sich bei den Feldern um Referenztypen handelt.

public override bool Equals(object obj) 
{ 
    if (obj == null) 
    { 
     return false; 
    } 
    RuntimeType type = (RuntimeType) base.GetType(); 
    RuntimeType type2 = (RuntimeType) obj.GetType(); 
    if (type2 != type) 
    { 
     return false; 
    } 
    object a = this; 
    if (CanCompareBits(this)) 
    { 
     return FastEqualsCheck(a, obj); 
    } 
    FieldInfo[] fields = type.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); 
    for (int i = 0; i < fields.Length; i++) 
    { 
     object obj3 = ((RtFieldInfo) fields[i]).UnsafeGetValue(a); 
     object obj4 = ((RtFieldInfo) fields[i]).UnsafeGetValue(obj); 
     if (obj3 == null) 
     { 
      if (obj4 != null) 
      { 
       return false; 
      } 
     } 
     else if (!obj3.Equals(obj4)) 
     { 
      return false; 
     } 
    } 
    return true; 
} 

In bestimmten Szenarien (wie den Werttyp als Schlüssel in einem Wörterbuch verwendet wird) kann die Leistung in einem Foul Swoop ermorden.

Verwandte Themen