2010-07-07 3 views
37

Beim Lernen von .net (von C#) habe ich 5 Möglichkeiten gefunden, die Gleichheit zwischen Objekten zu überprüfen.5 Möglichkeiten zur Überprüfung der Gleichheit in .net .. warum? und was zu verwenden?

  1. Die ReferenceEquals() -Methode.
  2. Die virtuelle Equals() -Methode. (System.Object)
  3. Die statische Equals() -Methode.
  4. Die Equals-Methode von IEquatable-Schnittstelle.
  5. Der Vergleichsoperator ==.

Meine Frage ist:

  1. Warum gibt es so viele Equals() -Methode zusammen mit Vergleichsoperator?
  2. Welche der virtuellen Equals() oder IEquatable der Equals() verwendet werden sholud .. (sagen wir, wenn wir unsere eigene Sammlung Klassen verwenden)

Antwort

26

1 - Referenz equals prüft, ob zwei Referenztypvariablen (Klassen, nicht Strukturen) auf dieselbe Speicheradresse verweisen.

2 - Die virtuelle Equals() -Methode prüft, ob zwei Objekte äquivalent sind.Lassen Sie uns sagen, dass Sie diese Klasse haben:

class TestClass{ 
    public int Property1{get;set} 
    public int Property2{get;set} 

    public override bool Equals(object obj) 
    { 
     if (obj.GetType() != typeof(TestClass)) 
      return false; 

     var convertedObj = (TestClass)obj; 

     return (convertedObj.Property1 == this.Property1 && convertedObj.Property2 == this.Property2); 
    } 
} 

und Sie instanziieren 2 Objekte aus dieser Klasse:

var o1 = new TestClass{property1 = 1, property2 = 2} 
var o2 = new TestClass{property1 = 1, property2 = 2} 

obwohl die beiden Objekte nicht die gleiche Instanz von Testclass sind, um den Anruf zu o1.Equals (o2) wird wahr zurückgeben.

3 - Die statische Equals-Methode wird verwendet, um Probleme zu behandeln, wenn bei der Prüfung ein Nullwert vorhanden ist. Stellen Sie sich vor, zum Beispiel:

TestClass o1 = null; 
var o2 = new TestClass{property1 = 1, property2 = 2} 

Wenn Sie versuchen, diese:

o1.Equals(o2); 

Sie eine Nullreferenceexception, weil o1 Punkte bekommen nichts wil. Um dieses Problem zu beheben, tun Sie dies:

Object.Equals (o1, o2);

Diese Methode ist für die Verarbeitung von Nullreferenzen vorbereitet.

4 - Die IEquatable-Schnittstelle wird von .Net zur Verfügung gestellt, so dass Sie innerhalb Ihrer Equals-Methode keine Umwandlungen durchführen müssen. Wenn der Compiler feststellt, dass Sie die Schnittstelle in einer Klasse für den Typ implementiert haben, den Sie auf Gleichheit prüfen möchten, wird dieser Methode Vorrang vor der Override Object.Equals (Object) gegeben. Zum Beispiel:

class TestClass : IEquatable<TestClass> 
{ 
    public int Property1 { get; set; } 
    public int Property2 { get; set; } 

    public override bool Equals(object obj) 
    { 
     if (obj.GetType() != typeof(TestClass)) 
      return false; 

     var convertedObj = (TestClass)obj; 

     return (convertedObj.Property1 == this.Property1 && convertedObj.Property2 == this.Property2); 
    } 

    #region IEquatable<TestClass> Members 

    public bool Equals(TestClass other) 
    { 
     return (other.Property1 == this.Property1 && other.Property2 == this.Property2); 
    } 

    #endregion 
} 

jetzt, wenn wir dies tun:

var o1 = new TestClass{property1 = 1, property2 = 2} 
var o2 = new TestClass{property1 = 1, property2 = 2} 
o1.Equals(o2); 

Die aufgerufene Methode ist Equals (Testclass) vor Equals (Object).

5 - Der Operator == bedeutet normalerweise dasselbe wie ReferenceEquals, es prüft, ob zwei Variablen auf die gleiche Speicheradresse zeigen. Das Problem besteht darin, dass dieser Operator für die Durchführung anderer Überprüfungen außer Kraft gesetzt werden kann. In Strings prüft es zum Beispiel, ob zwei verschiedene Instanzen äquivalent sind.

Dies ist eine nützliche Verbindung Gleichheiten in .Net besser zu verstehen:

+0

Excellent. Die Beispiele helfen wirklich, aber es gibt einen Tippfehler in deinem Punkt 4, wo das IEquatable.Equals immer noch 'convertedObj' verwendet – PaulG

+0

Danke PaulG, es ist jetzt behoben! =] – mverardo

29

Die Reference() -Methode.

Dies wird verwendet, um zu testen, ob zwei gegebene Variablen auf dasselbe Objekt zeigen (die Symbolreferenzen). Es entspricht wörtlich ((object)a) == ((object)b). Wenn Sie den Vergleichsoperator überschreiben (==), erhält ReferenceEquals eine Möglichkeit, auf das Standardverhalten zuzugreifen.

Allerdings, wenn Sie mit einem Werttyp (z. B. eine Struktur) dann diese will always return false befassen. Dies liegt daran, dass die Vergleichsboxen jeden Werttyp mit einem neuen Objekt verknüpfen, daher sind die Referenzen natürlich nicht gleich.


Die virtuellen equals() Methode. (System.Object)

Dies ist die Standardmethode zum semantischen Vergleich zweier Objekte (beliebigen Typs). Jede Klasse überschreibt diese nach Belieben. Standardmäßig entspricht dies einem CLR-Aufruf (InternalEquals), der grundsätzlich Speicherreferenzen vergleicht.

Hinweis, wenn zwei Objekte wahr für Equals() zurückgeben, dann GetHashCode() auf jedem von ihnen must be equal. Wenn jedoch die Hash-Codes für zwei Objekte wertäquivalent sind (d. H. obj1.GetHashCode() == obj2.GetHashCode()), bedeutet dies, dass nicht bedeutet, dass Equals() wahr ist.

Ihre Klasse sollte in der Regel implementieren Equals und GetHashCode als Mittel Klasseninstanzen zu unterscheiden, und muss dies oder das == Operator (idealerweise beide) implementieren, wenn es sich um ein Werttyp ist.

Hinweis für Werttypen der Standard Equals Verhalten ist, dass der ValueType.Equals() die, wenn Sie in Reflector aussehen (oder the MSDN description lesen) verwendet Reflektion, die Mitglieder der beiden Werte Instanzen zu vergleichen.


Die statischen equals() Methode. Diese

entspricht return ((objA == objB) || (((objA != null) && (objB != null)) && objA.Equals(objB))) wo jeder Typ Object zum Testen umgewandelt wird. Meine Tests zeigen, dass überladene Vergleichsoperatoren ignoriert werden, aber Ihre Equals-Methode wird verwendet, wenn die Objekte nicht null sind und nicht die gleiche Referenz sind. Daher ist a.Equals(b) nicht notwendigerweise gleich object.Equals(a, b) (für die Fälle, in denen ((object)a) == ((object)b) oder entweder a oder b null ist).


Die Methode equals aus IEquatable Schnittstelle.

IEquatable bietet eine Möglichkeit für Sie, Vergleiche mit Instanzen der gleichen Klasse speziell zu behandeln. Having said, die Ihre Equals Methode should be handling the behaviour the same way:

Wenn Sie Equals implementieren, sollten Sie auch die Basisklasse Implementierungen von Object.Equals (Object) und GetHashCode überschreiben so dass ihr Verhalten im Einklang mit der die IEquatable.Equals Methode

Nevertheless you should implement IEquatable:

die Möglichkeit zu behandeln, die eine Klasse Objekte werden oder ein generisches Sammelobjekt in einem Array gespeichert wird, ist es eine gute Idee, IEquatable so dass das Objekt implementieren kann manipulierte leicht identifiziert und sein.


Der Vergleichsoperator ==

Der Vergleichsoperator standardmäßig true zurück, wenn Ihre beiden Objekte die gleiche Referenz.

Es is not recommended den Vergleichsoperator außer Kraft zu setzen, wenn Sie with a value type handeln (in diesem Fall empfiehlt es sich, zusammen mit dem Equals Verfahren) oder ein unveränderlicher Referenztyp, die Sie in der Regel durch einen Wert (z string) vergleichen würden. Immer implementieren != zur gleichen Zeit (in der Tat bekomme ich einen requires a matching operator '!=' to also be defined Fehler, wenn ich nicht).


Ressourcen:

+2

Ausgezeichnete Antwort. +1 – RPM1984

0

Für Primitiven, Stick mit dem Operator ==.

In den meisten im .NET Framework bereitgestellten Objekten und beliebigen benutzerdefinierten Objekten erstellen Sie die .Equals() -Methode, und der Operator == überprüft nur, ob zwei Objekte auf dasselbe Objekt im Heap verweisen.

Der Zweck der IEquatable-Schnittstelle besteht darin, die .Equals() -Methode zu überschreiben, um ihr Verhalten von der Überprüfung auf referenzielle Gleichheit zu ändern, um auf Wertgleichheit zu prüfen. Der System.String-Typ ist ein Beispiel für ein integriertes .NET-Objekt, das diese Schnittstelle implementiert.

Die Methode .ReferenceEquals() bietet Entwicklern, die die Standardmethode .Equals() überschrieben haben, die Möglichkeit, zwei Objekte auf referenzielle Gleichheit zu überprüfen.

+2

"Primitive"? Das ist nicht Java, Mang! – Randolpho

1

Jede Version der Gleichheit ist etwas anders.

ReferenceEquals Tests für Referenzgleichheit.

virtual Equals sucht standardmäßig nach Referenzgleichheit für Klassentypen und Wertgleichheit für Strukturtypen. Es kann außer Kraft gesetzt werden, um Gleichheit anders zu definieren, falls gewünscht; und sollte für Werttypen überschrieben werden.

static Equals ruft nur virtual Equals, sondern ermöglicht auch null Argumente.

IEquatable<T>.Equals ist ein generisches/typsicheres Äquivalent für virtual Equals.

operator== ist wie der Standard virtual Equals gemeint, was die Referenzgleichheit für Klassentypen bedeutet (es sei denn, die Klasse überschreibt auch andere Operatoren). Es sollte auch für Werttypen außer Kraft gesetzt werden. Wenn Sie eine eigene Erfassungsklasse schreiben, verwenden Sie IEqualityComparer<T>, standardmäßig EqualityComparer<T>.Default. Verwenden Sie keinen der Gleichheitsvergleiche direkt.

+0

thnx .. zur Lösung von Zweifeln über die Implementierung unserer eigenen Collection-Klasse – Gaurav

Verwandte Themen