Pourquoi ne pas incrémenter Nullable jette une exception?

Pourriez-vous s’il vous plaît expliquer, pourquoi Console.WriteLine écrit une ligne vide ( Console.WriteLine(null) me donne une erreur de compilation) et pourquoi il n’y a pas NullReferenceException (même a+=1 ne devrait pas le déclencher)?

 int? a = null; a++; // Why there is not NullReferenceException? Console.WriteLine(a); // Empty line 

Vous observez les effets d’un opérateur soulevé .

De la section 7.3.7 de la spécification C # 5:

Les opérateurs levés permettent d’utiliser des opérateurs prédéfinis et définis par l’utilisateur qui opèrent sur des types de valeur non nullables avec des formes nullables de ces types. Les opérateurs levés sont construits à partir d’opérateurs prédéfinis et définis par l’utilisateur qui répondent à certaines exigences, comme décrit ci-après:

  • Pour les opérateurs unaires + ++ - -- ! ~ Une forme levée d’un opérateur existe si les types d’opérande et de résultat sont tous deux des types de valeur non nullables. La forme levée est construite en ajoutant un seul ? modificateur pour les types d’opérande et de résultat. L’opérateur levé produit une valeur nulle si l’opérande est nul. Sinon, l’opérateur levé ouvre l’opérande, applique l’opérateur sous-jacent et encapsule le résultat.

Donc, fondamentalement, a++ dans ce cas est une expression avec un résultat de null (en tant que int? ) Et la variable est laissée intacte.

Quand vous appelez

 Console.WriteLine(a); 

cela est encadré dans object , ce qui le convertit en une référence null, qui est imprimée comme une ligne vide.

La réponse de Jon est correcte mais j’appendais quelques notes supplémentaires.

Pourquoi Console.WriteLine(null) donne-t-il une erreur de compilation?

Il y a 19 surcharges de Console.WriteLine et trois d’entre elles s’appliquent à un null : celui qui prend une ssortingng , celle qui prend un char[] et celle qui prend un object . C # ne peut pas déterminer lequel de ces trois vous voulez dire, donc cela donne une erreur. Console.WriteLine((object)null) serait légal car maintenant c’est clair.

Pourquoi Console.WriteLine(a) écrit-il une ligne vide?

a est un int? nul int? . La résolution de surcharge choisit la version d’ object de la méthode, donc l’ int? est encadré à une référence nulle. Donc, c’est fondamentalement la même chose que Console.WriteLine((object)null) , qui écrit une ligne vide.

Pourquoi il n’y a pas NullReferenceException sur l’incrément?

Où est la référence null qui vous inquiète? a est un int? nul int? qui n’est pas un type de référence pour commencer! Rappelez-vous que les types de valeur nullable sont des types de valeur , pas des types de référence , donc ne vous attendez pas à ce qu’ils aient une sémantique de référence, sauf s’ils sont encadrés par un type de référence. Il n’y a pas de boxe dans l’addition.

Êtes-vous incrémentant null ???

 int? a = null; a++; 

Cette déclaration signifie simplement null++ c’est-à-dire null + 1.

Conformément à ce document, un type nullable peut représenter la plage de valeurs correcte pour son type de valeur sous-jacent, plus une valeur null supplémentaire. peut être atsortingbué la valeur nulle

Ici, vous incrémentez null, alors il deviendra également une valeur nulle et non 0 ou tout autre entier.

Pourquoi il imprime en blanc au lieu de l’erreur?

Lorsque vous imprimez un type nullable avec une valeur nulle, il imprime un champ vide au lieu d’une erreur car vous imprimez une variable, c’est-à-dire la valeur d’un emplacement de mémoire. qui peut être nul ou entier.

Mais lorsque vous essayez d’imprimer null en utilisant Console.WriteLine(null) , comme null n’est pas une variable, il ne se réfère donc à aucun emplacement de mémoire. Et par conséquent, il donne l’erreur "NullReferenceException" .

Alors, comment pouvez-vous imprimer un entier en utilisant Console.WriteLine(2); ??

Dans ce cas, 2 se mettra en mémoire à un emplacement temporaire et le pointeur pointera vers cet emplacement de mémoire pour imprimer.