2008-09-22 8 views
48

Also, als ich ein komparativer Neuling für den Anfänger war, dachte ich, dass diese beiden Dinge syntaktischer Zucker für einander waren, dh dass eine über die andere war einfach eine persönliche Vorliebe. Im Laufe der Zeit bin ich zu der Erkenntnis gekommen, dass diese beiden nicht identisch sind, selbst in einer Standardimplementierung (siehe this und this). Um die Sache weiter zu verwirren, kann jede davon separat überschrieben/überladen werden, um völlig unterschiedliche Bedeutungen zu haben.== vs. Object.Equals (Objekt) in .NET

Ist das eine gute Sache, was sind die Unterschiede, und wann/warum sollten Sie eines über dem anderen verwenden?

Antwort

17

MSDN hat klare und solide Beschreibungen beider Dinge.

object.Equals method

operator ==

Overloadable Operators

Guidelines for Overriding Equals() and Operator ==

Ist das eine gute Sache, was sind die Unterschiede, und wann/warum sollten Sie einen über den anderen verwenden ?

Wie kann es "gut" oder "schlecht" sein? Eine - Methode, eine andere - Operator. Wenn die Referenzgleichheit nicht ausreicht, überlasten Sie sie, andernfalls lassen Sie sie unverändert. Für primitive Typen funktionieren sie einfach out of box.

+0

Wenn jemand in Generika kommt, können die Unterschiede sehr groß sein, wenn man sie blind auf irgendeinen Typ T anruft. –

+2

"blind" ist eine schlechte Praxis für alles. Wenn Sie die Antwort auf Ihre Frage wissen, warum fragen? – aku

+0

Auch wenn ich eine konkrete Antwort kannte (was ich nicht weiß), vielleicht aus dem gleichen Grund, warum Leute Fragen stellen und sich selbst beantworten? Wie können Sie sonst noch etwas für einen generischen Typ T tun? Wenn Sie anfangen, Dinge wie if (typeof (T) == typeof (int)), was ist der Punkt? –

1

Mein Verständnis der Verwendungen von beiden war das: Verwenden Sie == für konzeptionelle Gleichheit (im Zusammenhang, diese beiden Argumente bedeuten das gleiche?), Und .Equals für konkrete Gleichheit (sind diese beiden Argumente in der Tat die genau dasselbe Objekt?).

Edit: Kevin Sheffield verlinkte Artikel hat einen besseren Job zu erklären Wert vs. Referenz Gleichheit ...

+0

Einverstanden, aber das hört sich nach einer guten Faustregel an. –

+0

Nicht korrekt. 'ReferenceEquals' ist der Identitäts-Test in .Net. Wenn "Equals" immer einen Identitätstest durchführt, dann hätte es keinen Sinn, beides zu haben ... – ToolmakerSteve

0

Sie könnten .Equals verwenden, da jemand zu einem späteren Zeitpunkt kommen und sie für Ihre Klasse überladen kann.

+0

Aber wäre das nicht eine gute Sache? –

+0

Ja, ich denke, ich wollte es anders herum sagen. –

33
string x = "hello"; 
string y = String.Copy(x); 
string z = "hello"; 

Um zu testen, ob x Punkte auf das gleiche Objekt wie y:

(object)x == (object)y // false 
x.ReferenceEquals(y) // false 
x.ReferenceEquals(z) // true (because x and z are both constants they 
         //  will point to the same location in memory) 

zu testen, um, wenn x den gleichen Zeichenfolge Wert wie y hat:

x == y  // true 
x == z  // true 
x.Equals(y) // true 
y == "hello" // true 

Beachten Sie, dass dies anders ist nach Java. In Java die == Betreiber nicht so ein häufiger Fehler in Java überlastet ist:

y == "hello" // false (y is not the same object as "hello") 

Für String-Vergleich in Java Sie immer .equals()

y.equals("hello") // true 
+2

Für Zeichenkettenoperator == vergleicht beide Zeichenketten durch Inhalte. Aber das ist nicht der Fall für andere Verweistypen. – Vaysage

+1

Ich möchte unterstreichen, was Vaysage gerade gesagt hat: Die Verwendung von "string" als Beispiel ist ** irreführend ** (oder zumindest unvollständig)). Es zeigt, wie Strings funktionieren. Aber String ist ein ** Sonderfall **. Um diese Antwort zu vervollständigen, kontrastiere eine "Zeichenkette" mit: (a) einem einzelnen Zeichen, (b) einem Array von Zeichen, (c) einer 'Struktur' mit mehreren Zeichenfeldern, (d) einer' Klasse' mit mehreren Zeichenfelder. Vielleicht müsste man sogar eine "Klasse" zeigen, die ein "struct" -Feld enthält oder ein "character array" -Feld enthält. Dann machen Sie verschiedene Aufgaben, zeigen Sie, wenn das Ergebnis immer noch "wahr" ist. – ToolmakerSteve

-1

Zwei der am häufigsten verwendeten Typen verwenden müssen, String und Int32, implementieren Sie sowohl Operator ==() und Equals() als Wert Gleichheit (anstelle von Referenzgleichheit).Ich denke, man kann diese beiden definierenden Beispiele betrachten, so ist meine Schlussfolgerung, dass beide identische Bedeutungen haben. Wenn Microsoft states otherwise, denke ich, dass sie absichtlich Verwirrung verursachen.

+1

Innerhalb von .net bewirken die Typen, die die Gleichheits-/Ungleichheitsoperatoren überschreiben, eine Gleichheit der Werte, aber C# fügt eine eigene Überladung der Gleichheits-/Ungleichheitsoperatoren hinzu, um die Referenzgleichheit von Objekten zu überprüfen, die keinen Wertgleichheitstest enthalten. Persönlich mag ich solch ein Sprachdesign nicht (vb.net verwendet die Operatoren 'Is' und' IsNot', um die Referenzgleichheit zu testen; wenn es auf Framework-Typen angewendet wird, wird '=' und '<>' die Wertgleichheit testen, wenn sie überhaupt kompiliert werden Es gibt jedoch nichts, was einen Typ daran hindern könnte, diese Operatoren zu überladen, um etwas völlig anderes zu bedeuten. – supercat

9

Da Microsofts aktuelle Aussage über die Gleichstellung Betreiber == und !=, ist die Schlussfolgerung: ==sollte nur syntaktischer Zucker sein für Object.Equals():

STELLEN SIE SICHER, dass Object.Equals und die Gleichstellung der Betreiber haben genau das gleiche Semantik

von http://msdn.microsoft.com/en-us/library/vstudio/7h9bszxx(v=vs.110).aspx

Dass sie unterscheidbar sind, anstatt nur Zucker, im Nachhinein scheint ein Fehler in ihrem Design zu sein.

Wenn Sie sicher sein wollen, erhalten Sie IDENTITY Vergleich (beim Vergleich von Referenzen), dann verwenden Sie stattdessen ReferenceEquals.

Leider ist der Umgang mit == so inkonsequent, dass ich es in der Regel zu vermeiden, wenn jemand anderes benutzerdefinierte Klassen zu manipulieren, und verwenden Sie nur die weniger lesbar Equals(a, b) oder ReferenceEquals(a, b), je nachdem, welche Bedeutung ich will.

IMHO, wäre es besser für Menschen, == und != überhaupt nicht zu implementieren. Lassen Sie einfach .Net standardmäßig auf Equals und ! Equals und implementieren Sie Equals entsprechend.

Wenn jemand andere Argumentation hat, würde ich es gerne hören.

(Und das ist wirklich verwirrend, wenn man bedenkt, dass Java zuerst existiert und == bedeutet ReferenceEquals. Aber es ist zu spät, um .Net so zu verhalten. Und wir haben Microsofts Statement zu diesem Zweck, in der Verbindung oben.)

+0

Ich fügte eine weitere Antwort hinzu, die deine Meinung ein wenig ändern könnte (nicht, dass ich deine Argumentation betrachte.) Aufruf von '.Equals()' auf Null object (Ausnahme ausgelöst) vs. Verwendung eines statischen Operators, der keinen der Operanden benötigt, um instanziiert zu werden (keine Ausnahme, funktioniert wie erwartet) – ps2goat

+0

Excellent answer: Thanks.In Bezug auf Ihren Kommentar an anderer Stelle auf dieser Seite über "verwirrt, warum viele von diesen Antworten Link zu diesem Artikel "- es ist StackOverflow: Es geht nicht darum, die vollständige Frage zu lesen und zu beantworten, es geht darum, wie schnell Sie etwas in der Frage selbst nitpick finden können. Deshalb warum die Person, die die Frage kritisiert s an der Spitze der Seite und Ihre Antwort, die schließlich dieses Chaos in .NET klärt, kämpft, um Stimmen zu erhalten. :-) –

-1

Operator == und Equals() sind beide gleich, während wir Werte anstelle von Referenzen vergleichen. Die Ausgabe beider ist gleich, siehe untenstehendes Beispiel.

Beispiel

static void Main() 
    { 
     string x = " hello"; 
     string y = " hello"; 
     string z = string.Copy(x); 
     if (x == y) 
     { 
      Console.WriteLine("== Operator"); 
     } 
     if(x.Equals(y)) 
     { 
      Console.WriteLine("Equals() Function Call"); 
     } 
     if (x == z) 
     { 
      Console.WriteLine("== Operator while coping a string to another."); 
     } 
     if (x.Equals(y)) 
     { 
      Console.WriteLine("Equals() Function Call while coping a string to another."); 
     } 
    } 

Ausgang:

== Operator 
    Equals() Function Call 
    == Operator while coping a string to another. 
    Equals() Function Call while coping a string to another. 
3

Ich würde dies auf der akzeptierte Antwort als Kommentar posten, aber ich denke, das bei der Bestimmung betrachtet werden verdient die Route zu nehmen.

dotnetfiddle: https://dotnetfiddle.net/gESLzO

Fiddle Code:

Object a = null; 
    Object b = new Object(); 

    // Ex 1 
    Console.WriteLine(a == b); 
    // Ex 2 
    Console.WriteLine(b == a); 

    // Ex 3  
    Console.WriteLine(b.Equals(a)); 
    // Ex 4 
    Console.WriteLine(a.Equals(b)); 

Die ersten 3 Console.WriteLine Beispiele funktionieren wird, aber die vierte eine Ausnahme auslöst.1 und 2 verwenden ==, was eine statische Methode ist, bei der keines der Objekte instanziiert werden muss.

Beispiel 3 funktioniert, weil b instanziiert wird.

Beispiel 4 schlägt fehl, weil anull ist, und daher kann eine Methode für ein Nullobjekt nicht aufgerufen werden.

Da ich versuche, so träge wie möglich zu codieren, verwende ich ==, besonders wenn ich mit Szenarien arbeite, in denen eines der beiden Objekte (oder beide) null sein kann. Wenn nicht, müsste ich zunächst einen Null-Check durchführen, bevor ich .Equals() anrufen kann.

+0

Beachten Sie, dass dies immer noch bei Strings auftritt. Und natürlich könnte der Operator außer Kraft gesetzt werden, aber die Essenz dieser Antwort besteht darin, dass Operatoren statisch sind und keine Nicht-Null-Instanzen für beide Operanden erfordern. – ps2goat