Sehen Sie sich zunächst den Vergleich zwischen grundlegenden Werttypen in CLR an, und schauen Sie sich zunächst den Code an:
int age1 = 30; int age2 = 30; Console.WriteLine("int == int: {0}", age1 == age2); Console.WriteLine("int == int: {0}", age2 == age1); Console.WriteLine("int Equals int: {0}", age1.Equals(age2)); Console.WriteLine("int Equals int: {0}", age2.Equals(age1)); Console.WriteLine("int ReferenceEquals int: {0}", object.ReferenceEquals(age1, age2)); Console.WriteLine("int ReferenceEquals int: {0}", object.ReferenceEquals(age2, age1)); Console.ReadLine();
Laufende Ergebnisse:
Für die gleich grundlegend Für Werttypen (im obigen Beispielcode sind beide int) sind die Vergleichsergebnisse von == und Equals() gleich, da ReferenceEquals() bestimmt, ob die Referenzen zweier Objekte gleich sind, für Werttypen muss dies der Fall sein Die Box-Operation muss jedes Mal ein temporäres Objekt generieren und daher immer „false“ zurückgeben. Als nächstes ändere ich den Typ von age2 im Code in den Byte-Typ. Was passiert mit den Vergleichsergebnissen? Schauen Sie sich bitte die laufenden Ergebnisse an:
Jetzt stellen wir fest, dass die Ergebnisse von age1.Equals(age2) und age2.Equals(age1) unterschiedlich sind. Beim Vergleich grundlegender Werttypen vergleicht == den Inhalt von „Wert“. Wenn der „Wert“ zweier Objekte gleich ist, sind die beiden Objekte „==“; Punkt: In Equal () gibt es tatsächlich einen Prozess der „impliziten Konvertierung“, was bedeutet, dass age1.Equals (age2) im obigen Code äquivalent zu int.Equals (int) ist und Bytedaten implizit in Daten vom Typ Int konvertiert werden können , also ist das Ergebnis von age1.Equals(age2) wahr; und age2.Equals(age1) ist äquivalent zu byte.Equals(byte), aber Daten vom Typ int können nicht implizit in den Typ Byte konvertiert werden, da die Möglichkeit eines Verlusts von besteht Datenpräzision. Tatsächlich sollte Equals() von age2.Equals(age1) dem folgenden Code ähneln:
public override bool Equals(object obj) { if (!(obj is Byte)) { return false; } return m_value == ((Byte)obj).m_value; }
Wenn es sich um eine explizite Konvertierung handelt, ist das Ergebnis von age2.Equals((byte)age1) wird zu diesem Zeitpunkt wahr sein.
Lassen Sie uns über den Vergleich zwischen String-Typen sprechen. String ist ein besonderer Referenztyp, da er „unveränderlich“ ist. Schauen wir uns zuerst den Code an:
string name1 = "Jack"; string name2 = "Jack"; object o1 = name1; object o2 = name2; Console.WriteLine("name1 == name2: {0}", name1 == name2); Console.WriteLine("name1 Equals name2: {0}", name1.Equals(name2)); Console.WriteLine("o1 == o2: {0}", o1 == o2); Console.WriteLine("o1 Equals o2: {0}", o1.Equals(o2)); Console.WriteLine("o1 == name2: {0}", o1 == name2); Console.WriteLine("o1 Equals name2: {0}", o1.Equals(name2)); Console.WriteLine("name1 ReferenceEquals name2: {0}", object.ReferenceEquals(name1, name2)); Console.WriteLine("o1 ReferenceEquals o2: {0}", object.ReferenceEquals(o1, o2)); Console.ReadLine();
Die obigen Ergebnisse der Codeausführung:
Die Vergleichsergebnisse sind alle wahr. Jetzt werden wir sie einzeln erklären um eins. Einige Leute werden sagen, dass Name1 und Name2 beide „Jack“ speichern, also sind Name1 und Name2 tatsächlich dasselbe Objekt, sodass die Vergleichsergebnisse von Name1==Name2 und Name1.Equals(Name2) gleich sind. Wenn wir den Quellcode einer Zeichenfolge mit dem .NET Reflector-Tool anzeigen, sehen wir diesen Codeabschnitt:
Der Operator == gibt tatsächlich Equals() zurück. Für die Erklärung, warum die Vergleichsergebnisse von name1==name2 und name1.Equals(name2) gleich sind, halte ich diese Erklärung für intuitiver als „name1 und name2 sind tatsächlich dasselbe Objekt“.
Wir wissen, dass die CLR aufgrund der Besonderheit des String-Typs mehrere identische String-Inhalte über ein String-Objekt gemeinsam nutzen kann, sodass der obige Name1 und Name2 auf dieselbe Stelle verweisen und das folgende o1 == o2 , o1 == name2, die Vergleichsergebnisse von object.ReferenceEquals(name1, name2) sind alle wahr, was auch diese Aussage bestätigt (tatsächlich ist object.ReferenceEquals(name1, o2) auch wahr). Was aber, wenn die Zuordnung von Name1 und Name2 so wird?
string name1 = new string(new char[] { 'J', 'a', 'c', 'k' }); string name2 = new string(new char[] { 'J', 'a', 'c', 'k' });
Sehen Sie sich die laufenden Ergebnisse an:
Die Vergleichsergebnisse von name1==name2 und name1.Equals(name2) sind ebenso leicht zu verstehen , wie oben erwähnt Ja, der Operator == gibt tatsächlich Equals() zurück (bei Referenztypen vergleicht Equals() die auf dem verwalteten Heap gespeicherten Inhalte), sodass die Ergebnisse der beiden gleich sind. Beim Vergleich der Objektobjekte o1 und o2 sind die Ergebnisse von o1 == o2 und o1.Equals(o2) jedoch unterschiedlich. == von Objektobjekten vergleicht Typobjektzeiger. o1 und o2 sind zwei Objekte, und ihre Typobjektzeiger müssen unterschiedlich sein. Equals() vergleicht den Inhalt von o1 und o2, der auf dem verwalteten Heap gespeichert ist WAHR. Dies zeigt auch, dass das folgende o1 == name2 falsch und o1.Equals(name2) wahr ist.
Werfen wir zunächst einen Blick auf den Code in object.ReferenceEquals:
Jetzt für object.ReferenceEquals(name1, name2) und object.ReferenceEquals(o1 , o2 ) Die Ergebnisse sind alle falsch. Es sollte leicht zu verstehen sein. Tatsächlich handelt es sich um ein == Problem zwischen zwei Objekten!
Lassen Sie uns abschließend über den Vergleich benutzerdefinierter Referenztypen sprechen.
class MyName { private string _id; public string Id { get { return _id; } set { _id = value; } } public MyName(string id) { this.Id = id; } }
Ändern Sie die Deklarationen von name1 und name2 oben in:
MyName name1 = new MyName("12"); MyName name2 = new MyName("12");
Andere bleiben unverändert und das laufende Ergebnis ist:
name1 und name2 sind zwei völlig unterschiedliche Objekte. Es sollte leicht zu verstehen sein, dass die Vergleichsergebnisse alle falsch sind.
Verstehen Sie ==, Equals() und ReferenceEquals in C# mehr auf einmal. Für verwandte Artikel Informationen zum Unterschied zwischen () finden Sie auf der chinesischen PHP-Website!