Pourquoi est-ce que l’opérateur is retourne false lorsqu’il est donné null?

Il me semble que l’opérateur est un peu incohérent.

 bool Test() { // Returns false, but should return true. return null is ssortingng; } 

On s’attend à ce que la valeur null appartienne à tout type de référence (ou nullable). Et en effet, la spécification du langage C # dit quelque chose qui supporte cette hypothèse, par exemple (6.1.6 Conversions de références implicites):

Les conversions de référence implicites sont les suivantes:

• Du littéral nul à tout type de référence.

La description (7.10.10 L’opérateur is) de l’opérateur is commence par dire que l’expression (E is T) donnera true quand une conversion de référence de E à T existe, mais ensuite les auteurs excluent explicitement le cas lorsque E est le littéral null ou a une valeur null .

Pourquoi font-ils ça? Pour moi, cela semble contre-intuitif.

Cette question a fait l’ object de mon blog le 30 mai 2013 . Merci pour la bonne question!


Vous regardez fixement une allée vide.

Quelqu’un vous demande “Votre allée peut-elle contenir une Honda Civic?”

Oui. Oui il peut.

Quelqu’un vous indique une seconde allée. Il est également vide. Ils demandent “Est-ce que le contenu actuel de mon allée peut entrer dans votre entrée?”

Oui bien sûr. Les deux allées sont vides! Donc, clairement, le contenu de l’un peut s’intégrer dans l’autre, car il n’ya aucun contenu de l’un ou de l’autre en premier lieu.

Quelqu’un vous demande “Votre allée contient-elle une Honda Civic?”

Non.

Vous pensez que l’opérateur is répond à la deuxième question: compte tenu de cette valeur, correspond-il à une variable de ce type? Une référence null correspond-elle à une variable de ce type? Oui.

Ce n’est pas la question à laquelle l’opérateur répond. La question à laquelle l’opérateur répond est la troisième question. y is X ne demande pas ” y est-il une valeur légale d’une variable de type X ? ” Il demande ” Est-ce qu’une référence valide à un object de type X ? ” Comme une référence nulle n’est pas une référence valide à un object quelconque tapez, la réponse est “non”. Cette allée est vide; il ne contient pas de Honda Civic.

Une autre façon de le voir est que y is X répond à la question “si je disais y as X , aurais-je un résultat non nul? Si y est nul, la réponse est clairement non!


Pour approfondir un peu votre question:

On s’attend à ce que la valeur null appartienne à tout type de référence (ou nullable)

On supposerait implicitement qu’un type est un ensemble de valeurs et que la compatibilité d’affectation d’une valeur y avec une variable de type X n’est ni plus ni moins que de vérifier si y est membre de l’ensemble x .

Bien que ce soit une manière extrêmement courante de regarder les types, ce n’est pas la seule façon de regarder les types, et ce n’est pas ainsi que C # examine les types. Les références NULL sont des membres sans type en C #; la compatibilité des affectations ne consiste pas simplement à vérifier un ensemble pour voir s’il contient une valeur. Le fait qu’une référence nulle soit affectée à une variable de type référence X ne signifie pas que null est un membre de type X. La relation “est affectation compatible avec” et la relation “est membre de type” ont évidemment beaucoup de se chevauchent, mais ils ne sont pas identiques dans le CLR.

Si des reflections sur la théorie des types vous intéressent, consultez mes articles récents sur le sujet:

Quelle est cette chose que vous appelez un “type”? Partie un

Quelle est cette chose que vous appelez un “type”? Deuxième partie

Le littéral null peut être affecté à n’importe quel type de référence. Ce n’est pas un type en soi. C’est un littéral spécial qui représente une référence nulle.

Dans le cas où cela retournerait true quand un null serait passé, que pourriez-vous faire avec le littéral null ? Rien – c’est null . À quoi cela servirait-il de revenir, sauf en cas de confusion?


Indépendamment de la manière dont c’est intuitif, lisez le code en anglais et dites-moi:

 null is ssortingng; 

Quand je vois cela, il semble que la question is "nothing" a ssortingng? . Mon intuition me dit que non, ce n’est pas – ce n’est nothing .

Je pense que null is ssortingng retourne false est très intuitive. Null ne veut rien dire et ce n’est certainement pas une corde. Donc, il devrait retourner faux. Bien que ce soit un choix que les concepteurs de langage ont fait, il est très intuitif quand on considère la signification réelle de null.

http://msdn.microsoft.com/en-us/library/scekt9xw%28v=vs.71%29.aspx

Une expression is est évaluée à true si les deux conditions suivantes sont remplies:

  • l’expression n’est pas nulle.
  • expression peut être converti en type. C’est-à-dire qu’une expression de type cast (type (expression) se terminera sans lancer d’exception. Pour plus d’informations, voir 7.6.6 Convertir des expressions.

En pratique, le fait d’avoir “null est T == false” évite de taper du code supplémentaire:

Au lieu de dire

 if (X != null && X is Foo) {} 

Je peux juste dire

 if (X is Foo) {} 

et finis-en.

la valeur null

Je l’ai cité de votre question parce que cela semble aller au coeur du problème. null n’est pas une valeur – c’est l’absence d’une valeur. Le but de is pour moi semble être de répondre à la question:

Si je lance E vers T , vais-je réussir avec un T ?

Maintenant, alors que vous pouvez convertir null en T sans erreur , après cela, vous n’avez pas de T – vous n’avez toujours rien. Donc, ce n’est pas le cas si null “est” un T , donc retourne faux.

En Java, il y a un opérateur qui fait exactement la même chose, mais son nom est beaucoup plus long: instanceof . Il est très intuitif que null instanceof Ssortingng renvoie false, car null n’est pas une instance de quoi que ce soit, et encore moins une Ssortingng . Ainsi, lorsque vous utilisez null la version de Java est un peu plus intuitive.

Cependant, ces deux opérateurs renvoient la valeur true lorsqu’on leur demande de parcourir toute la hiérarchie. Par exemple. si instance de Ssortingng est un Object . Et ici, Java est un peu moins intuitif (car une instance en a un en fait, un type très spécifique) et le C # est plus intuitif (parce que chaque Ssortingng est un Object profond).

Bottom line: si vous essayez de décrire une logique assez avancée en un mot, vous ne pouvez que confondre peu de personnes, de cette façon ou d’une autre. Il semble que la plupart des gens étaient d’accord sur un sens et que ceux qui n’étaient pas d’accord devaient s’adapter.