En C # 7, nous pouvons utiliser
if (x is null) return;
au lieu de
if (x == null) return;
Y a-t-il des avantages à utiliser la nouvelle méthode (ancien exemple) par rapport à l'ancienne?
La sémantique est-elle différente?
Est-ce juste une question de goût? Sinon, quand devrais-je utiliser l'un sur l'autre?
Référence: Nouveautés de C # 7.0 .
Réponses:
Mise à jour: le compilateur Roslyn a été mis à jour pour rendre le comportement des deux opérateurs identique lorsqu'il n'y a pas d'opérateur d'égalité surchargé . Veuillez voir le code dans les résultats du compilateur actuel (
M1
etM2
dans le code) qui montre ce qui se passe quand il n'y a pas de comparateur d'égalité surchargé. Ils ont maintenant tous deux le comportement le plus performant==
. S'il existe un comparateur d'égalité surchargé, le code diffère toujours .Voir pour les anciennes versions du compilateur Roslyn l'analyse ci-dessous.
Car
null
il n'y a pas de différence avec ce à quoi nous sommes habitués avec C # 6. Cependant, les choses deviennent intéressantes lorsque vous passeznull
à une autre constante.Prenez ceci par exemple:
Le test donne
a
. Si vous comparez cela ào == (object)1
ce que vous auriez écrit normalement, cela fait une énorme différence.is
prend en considération le type de l'autre côté de la comparaison. C'est cool!Je pense que le modèle
== null
vsis null
constant est juste quelque chose de très familier «par accident», où la syntaxe de l'is
opérateur et de l'opérateur égal donne le même résultat.Comme svick a commenté, les
is null
appelsSystem.Object::Equals(object, object)
où les==
appelsceq
.IL pour
is
:IL pour
==
:Puisque nous parlons
null
, il n'y a pas de différence car cela ne fait qu'une différence sur les instances . Cela peut changer lorsque vous avez surchargé l'opérateur d'égalité.la source
is
appelsobject.Equals(x, null)
, tandis que se==
compile commeceq
. Mais le résultat devrait être le même, comme vous l'avez dit.==
s'agit d'un opérateur surchargeable. Vous pouvez avoir n'importe quel comportement que vous souhaitez avec. Par exemple, cette implémentation bizarre==
ne vous dira pas si votre instance est vraiment nulle.is null
d'autre part, retournera toujours vrai pour les vraies références nulles :) De plus, si vous avezReferenceEquals
dans votre code, les ampoules VS 2017 suggéreront de passer àis null
, pas== null
(correctement).is
n'a plus la surcharge d'un appel de fonction lorsqu'il est utilisé pour vérifier la nullité. Pour preuve, voir le lien posté par @svick dans les commentaires.Surchargé est égal à l'opérateur
Il existe en fait une différence de sémantique entre les deux comparaisons lorsque vous comparez
null
avec un type qui a surchargé l'==
opérateur.foo is null
utilisera la comparaison de référence directe pour déterminer le résultat, tandis quefoo == null
, bien sûr, exécutera l'==
opérateur surchargé s'il existe.Dans cet exemple, j'ai introduit un "bogue" dans l'
==
opérateur surchargé , ce qui lui fait toujours lever une exception si le deuxième argument estnull
:Le code IL pour
foo is null
utilise l'ceq
instruction pour effectuer une comparaison de référence directe:Le code IL pour
foo == null
utilise un appel à l'opérateur surchargé:La différence est donc que si vous utilisez,
==
vous risquez d'exécuter du code utilisateur (qui peut potentiellement avoir des problèmes de comportement ou de performance inattendus).Restriction sur les génériques
L'utilisation de la
is null
construction limite le type à un type de référence. Le compilateur le garantit, ce qui signifie que vous ne pouvez pas l'utiliseris null
sur un type de valeur. Si vous avez une méthode générique, vous ne pourrez l'utiliseris null
que si le type générique est contraint à être un type de référence.Merci à David Augusto Villa de l' avoir signalé.
la source