Mein Verständnis dieser drei war:
.Equals()
Tests zur Datengleichheit (mangels einer besseren Beschreibung)..Equals()
kann True für verschiedene Instanzen desselben Objekts zurückgeben, und dies ist die am häufigsten überschriebene Methode..ReferenceEquals()
Testet, ob zwei Objekte dieselbe Instanz sind und nicht überschrieben werden können.==
ist die gleiche wie dieReferenceEquals()
Standardeinstellung, kann jedoch überschrieben werden.
Aber C # Station sagt:
In der Objektklasse sind die Methoden
Equals
undReferenceEquals
semantisch äquivalent, außer dass die MethodenReferenceEquals
nur für Objektinstanzen funktionieren. DieReferenceEquals
Methode ist statisch.
Jetzt verstehe ich es nicht. Kann jemand etwas Licht ins Dunkel bringen?
Antworten:
Die Ursache Ihrer Verwirrung scheint zu sein, dass der Auszug aus der C # -Station einen Tippfehler enthält, der lauten sollte: "... außer dass Equals nur für Objektinstanzen funktioniert. Die ReferenceEquals-Methode ist statisch."
Sie haben lose Recht mit den Unterschieden in den semantischen Bedeutungen der einzelnen (obwohl "verschiedene Instanzen desselben Objekts" ein wenig verwirrt erscheinen, sollte es wahrscheinlich "verschiedene Instanzen desselben Typs " lauten ) und über die überschrieben werden kann.
Wenn wir das beiseite lassen, wollen wir uns mit dem letzten Teil Ihrer Frage befassen, dh wie sie mit einfachen
System.Object
Instanzen undSystem.Object
Referenzen funktionieren (wir müssen beide der nicht-polymorphen Natur von ausweichen==
). Hier funktionieren alle drei Operationen gleich , jedoch mit einer Einschränkung:Equals
Kann nicht aufgerufen werdennull
.Equals
ist ein Beispiel , das Verfahren nimmt einen Parameter (die kann seinnull
). Da es sich um eine Instanzmethode handelt (die für ein tatsächliches Objekt aufgerufen werden muss), kann sie nicht für einenull
Referenz aufgerufen werden .ReferenceEquals
ist eine statische Methode, die zwei Parameter verwendet, von denen einer / beide sein könnennull
. Da sie statisch ist (nicht mit einem Objekt verbunden Beispiel ), wird es nicht ein WurfNullReferenceException
unter keinen Umständen.==
ist ein Operator, der sich in diesem Fall (object
) identisch verhältReferenceEquals
. Es wird auch kein werfenNullReferenceException
.Um zu zeigen:
quelle
.Equals()
)?object
Klasse" . Ich denke, Sie haben diesen Teil übersprungen? Denn sonst würden Sie nicht darüber reden, es zu überschreiben.object
Klasse.Equals
ist auch eine statische Methode, beiobject
der zwei Parameter verwendet werden. Einer oder beide können dann seinnull
.Schauen Sie sich diesen MSDN-Artikel zu diesem Thema an.
Ich denke, die relevanten Punkte sind:
Hoffe das hilft!
quelle
Ihr Verständnis von .ReferenceEquals ist korrekt.
.Equals überprüft die Datengleichheit für Werttypen und die Referenzgleichheit für Nichtwerttypen (allgemeine Objekte).
Gleichheiten können für Objekte überschrieben werden, um eine Form der Datengleichheitsprüfung durchzuführen
EDIT: Außerdem kann .ReferenceEquals nicht für Werttypen verwendet werden (nun, es kann, wird aber immer falsch sein).
quelle
Ich möchte meine fünf Cent zum Vergleich mit "null" hinzufügen.
ReferenceEquals (Objekt, Objekt) ist dasselbe wie "(Objekt) arg1 == arg2" (bei Werttypen erhalten Sie also Boxen und es braucht Zeit). Diese Methode ist jedoch die einzige 100% sichere Methode, um Ihr Argument in verschiedenen Situationen auf Null zu überprüfen, z
== und Equals (). Warum sage ich, dass ReferenceEquals bei Nullprüfungen 100% sicher ist? Stellen Sie sich vor, Sie schreiben generische Erweiterungen in projektübergreifende Kernbibliotheken und beschränken den generischen Parametertyp auf einen bestimmten Domänentyp. Dieser Typ kann den Operator "==" einführen - jetzt oder später (und glauben Sie mir, ich habe viel gesehen, dieser Operator kann eine sehr "seltsame" Logik haben, insbesondere wenn es um Domänen- oder Persistenzobjekte geht). Sie versuchen, Ihr Argument auf null zu überprüfen und rufen dann die Member-Operation auf. Überraschung, Sie können hier NullRef haben. Weil der Operator == fast mit Equals () identisch ist - sehr benutzerdefiniert und sehr unvorhersehbar. Es gibt jedoch einen Unterschied, der berücksichtigt werden sollte: Wenn Sie Ihren generischen Parameter nicht auf einen benutzerdefinierten Typ beschränken (== kann nur verwendet werden, wenn Ihr Typ "Klasse" ist), ist der Operator == derselbe wie das Objekt . ReferenceEquals (..). Die Implementierung von Equals wird immer vom endgültigen Typ verwendet, da sie virtuell ist.
Meine Empfehlung lautet also, wenn Sie Ihre eigenen Typen schreiben oder von bekannten Typen ableiten, können Sie == verwenden, um nach Null zu suchen. Verwenden Sie andernfalls object.ReferenceEquals (arg, null).
quelle
In der Objektklasse .Equals implementiert Identität, nicht Gleichheit. Es wird geprüft, ob die Referenzen gleich sind. Der Code könnte folgendermaßen aussehen:
Während der Implementierung von .Equals in Ihrer Klasse sollten Sie die Basisklasse .Equals nur aufrufen, wenn die Basisklasse nicht Object ist. Ja, das ist kompliziert.
Darüber hinaus können abgeleitete Klassen .Equals überschreiben, sodass Sie sie nicht aufrufen können, um die Identität zu überprüfen. Microsoft hat die statische .ReferenceEquals-Methode hinzugefügt.
Wenn Sie eine Klasse verwenden, werden für Sie logisch .Equals auf Gleichheit und .ReferenceEquals auf Identität geprüft.
quelle
Ich habe Anis hervorragende Antwort erweitert , um die wichtigsten Unterschiede beim Umgang mit Referenztypen und überschriebenen Gleichheitsmethoden aufzuzeigen.
Language: C# Program
..
quelle
Equals()
prüft je nach zugrunde liegendem Typ (Wert / Referenz) auf Hash-Code oder Äquivalenz undReferenceEquals()
soll immer nach Hash-Code suchen.ReferenceEquals
Gibt zurück,true
wenn beide Objekte auf denselben Speicherort zeigen.quelle