In C # 7 können wir verwenden
if (x is null) return;
anstatt
if (x == null) return;
Gibt es irgendwelche Vorteile bei der Verwendung des neuen Weges (früheres Beispiel) gegenüber dem alten Weg?
Ist die Semantik anders?
Ist nur Geschmackssache? Wenn nicht, wann sollte ich eins über das andere verwenden?
Referenz: Neues in C # 7.0 ist .
Antworten:
Update: Der Roslyn-Compiler wurde aktualisiert, um das Verhalten der beiden Operatoren zu ändern, wenn kein überladener Gleichheitsoperator vorhanden ist . Bitte beachten Sie den Code in den aktuellen Compiler-Ergebnissen (
M1
undM2
im Code), der zeigt, was passiert, wenn kein überladener Gleichheitsvergleich vorhanden ist. Beide haben jetzt das leistungsfähigere==
Verhalten. Wenn es einen überladenen Gleichheitsvergleich gibt, unterscheidet sich der Code immer noch .Siehe für ältere Versionen des Roslyn-Compilers die folgende Analyse.
Denn
null
es gibt keinen Unterschied zu dem, was wir mit C # 6 gewohnt sind. Wenn Sie jedochnull
zu einer anderen Konstante wechseln, werden die Dinge jedoch interessant .Nehmen Sie zum Beispiel:
Der Test ergibt
a
. Wenn Sie das mit dem vergleichen,o == (object)1
was Sie normalerweise geschrieben hätten, macht es einen verdammt großen Unterschied.is
berücksichtigt den Typ auf der anderen Seite des Vergleichs. Das ist cool!Ich denke, das
== null
vs.is null
konstante Muster ist nur etwas, das "aus Versehen" sehr vertraut ist, wobei die Syntax desis
Operators und des Operators gleich dem gleichen Ergebnis liefert.Wie svick kommentierte,
is null
ruftSystem.Object::Equals(object, object)
wo==
Anrufe anceq
.IL für
is
:IL für
==
:Da es sich um einen Unterschied handelt
null
, gibt es keinen Unterschied, da dies nur bei Instanzen einen Unterschied macht . Dies kann sich ändern, wenn Sie den Gleichheitsoperator überladen haben.quelle
is
Aufrufeobject.Equals(x, null)
, während==
kompiliert alsceq
. Aber das Ergebnis sollte das gleiche sein, wie Sie sagten.==
es sich um einen überlastbaren Bediener handelt. Sie können damit jedes gewünschte Verhalten haben. Zum Beispiel sagt Ihnen diese seltsam implementierte==
nicht, ob Ihre Instanz wirklich null ist.is null
Auf der anderen Seite wird immer true für echte Nullreferenzen zurückgegeben :) Wenn SieReferenceEquals
in Ihrem Code haben, schlagen VS 2017-Glühbirnen voris null
, nicht== null
(korrekt) zu ändern .is
bei der Überprüfung auf Null nicht mehr der Aufwand eines Funktionsaufrufs anfällt . Zum Beweis siehe den von @svick geposteten Link in den Kommentaren.Überladen ist gleich Operator
Tatsächlich gibt es einen Unterschied in der Semantik zwischen den beiden Vergleichen, wenn Sie
null
mit einem Typ vergleichen, der den==
Operator überlastet hat .foo is null
verwendet einen direkten Referenzvergleich, um das Ergebnis zu bestimmen, währendfoo == null
der überladene==
Operator natürlich ausgeführt wird , falls vorhanden.In diesem Beispiel habe ich einen "Fehler" im überladenen
==
Operator eingeführt, der dazu führt, dass immer eine Ausnahme ausgelöst wird, wenn das zweite Argument lautetnull
:Der IL-Code für
foo is null
verwendet dieceq
Anweisung, um einen direkten Referenzvergleich durchzuführen:Der IL-Code für
foo == null
verwendet einen Aufruf an den überladenen Operator:Der Unterschied besteht also darin, dass Sie bei Verwendung
==
das Risiko eingehen, Benutzercode auszuführen (was möglicherweise zu unerwartetem Verhalten oder Leistungsproblemen führen kann).Beschränkung auf Generika
Durch die Verwendung des
is null
Konstrukts wird der Typ auf einen Referenztyp beschränkt. Der Compiler stellt dies sicher, was bedeutet, dass Sie nichtis null
für einen Werttyp verwenden können. Wenn Sie über eine generische Methode verfügen, können Sie diese nur verwenden,is null
wenn der generische Typ auf einen Referenztyp beschränkt ist.Vielen Dank an David Augusto Villa für diesen Hinweis.
quelle