Warum gibt dieser Code true zurück:
new Byte() == new Byte() // returns true
Dieser Code gibt jedoch false zurück:
new Byte[0] == new Byte[0] // returns false
Warum gibt dieser Code true zurück:
new Byte() == new Byte() // returns true
Dieser Code gibt jedoch false zurück:
new Byte[0] == new Byte[0] // returns false
Antworten:
Da new Byte()
erstellt Werttyp, die nach Wert verglichen werden (standardmäßig wird byte
mit Wert zurückgegeben 0
). Und new Byte[0]
erstellt ein Array, das ein Referenztyp ist und mit einer Referenz verglichen wird (und diese beiden Instanzen des Arrays haben unterschiedliche Referenzen).
Weitere Informationen finden Sie im Artikel Werttypen und Referenztypen .
Bytes sind Werttypen in .NET. Dies bedeutet, dass der ==
Operator genau dann true zurückgibt, wenn die beiden Bytes denselben Wert haben. Dies wird auch als Wertgleichheit bezeichnet .
Arrays sind jedoch Referenztypen in .NET. Dies bedeutet, dass der ==
Operator genau dann true zurückgibt, wenn sie auf dieselbe Array-Instanz im Speicher verweisen. Dies wird auch als Referenzgleichheit oder Identität bezeichnet .
Beachten Sie, dass der ==
Operator sowohl für Referenz- als auch für Werttypen überladen werden kann. System.String
Dies ist beispielsweise ein Referenztyp, aber der ==
Operator für Zeichenfolgen vergleicht jedes Zeichen im Array nacheinander. Siehe Richtlinien zum Überladen von Equals () und Operator == (C # -Programmierhandbuch) .
Wenn Sie testen möchten, ob die Arrays (in der richtigen Reihenfolge) genau dieselben Werte enthalten , sollten Sie die Verwendung von Enumerable.SequenceEqual
anstelle von in Betracht ziehen ==
.
==
Betreiber und seine duale Natur. Diese Antwort deckt das klar ab.
System.Array
Klasse keine Überladung bereitstellt, wird die Standardreferenzgleichheit verwendet. Sie könnten denken, Sie könnten Ihren eigenen Array-Typ erstellen ( System.Array
ist schließlich abstrakt), aber der Compiler erlaubt Ihnen nicht, davon zu erben. Sie könnten wahrscheinlich mit einer subtilen Verwendung impliziter Operatoren ziemlich nahe kommen, um das Array in einen anderen Typ umzuwandeln, aber genau die Idee lässt meine Haut kriechen.
Beim Vergleichen der Referenz wird tatsächlich die Zeigeradresse verglichen, die unterschiedlich ist. Dies ist der Grund, warum false zurückgegeben wird, und bei der Wertadresse spielt es keine Rolle, ob der Wert verglichen wird.
Der Compiler versucht, den Werttyp in Registern zu speichern, aber aufgrund der begrenzten Registernummer erfolgt die weitere Speicherung im Stapel mit den Werten [Referenz], während sich der Referenztyp im Stapel befindet, der Wert jedoch eine Adresse der Speicheradresse im Heap enthält.
Vergleichen Sie hier den im Stapel vorhandenen Wert, der im ersten Fall für beide gleich ist, während im zweiten Fall die Adressen des Heaps unterschiedlich sind.
new Byte()
Aufrufe wahrscheinlich in Registern gespeichert sind.
Es gibt eine Überlastung des ==
Operators, bei der beide Operanden vom Typ sind, byte
und es wird implementiert, um den Wert jedes Bytes zu vergleichen. In diesem Fall haben Sie zwei Null-Bytes, die gleich sind.
Der ==
Operator ist für Arrays nicht überladen, daher object
wird object
im zweiten Fall die Überladung mit zwei Operanden verwendet (da Arrays vom Typ sind ), und ihre Implementierung vergleicht die Verweise auf die beiden Objekte. Der Verweis auf die beiden Arrays ist unterschiedlich.
Es ist erwähnenswert, dass dies (direkt) nichts mit der Tatsache zu tun hat, dass byte
es sich um einen Werttyp handelt und Arrays Referenztypen sind. Der ==
Operator für byte
hat nur dann eine Wertsemantik, weil bei dieser Implementierung eine bestimmte Überlastung des Operators vorliegt. Wenn diese Überladung nicht vorhanden wäre , gäbe es keine Überladung, für die zwei Bytes gültige Operanden wären, und als solche würde der Code überhaupt nicht kompiliert . Sie können dies leicht genug erkennen, indem Sie eine benutzerdefinierte struct
Datei erstellen und zwei Instanzen davon mit dem ==
Operator vergleichen. Der Code wird nicht kompiliert, es sei denn, Sie stellen Ihre eigene Implementierung ==
für diese Typen bereit .