2010-01-28 7 views

Répondre

10

Ceci est conforme à la spécification relative aux opérateurs binaires levés. De §7.2.7:

Pour les opérateurs binaires

+ - */% & |^<< >>

une forme levée d'un opérateur existe si les types d'opérandes et de résultat sont tous les types de valeur non nulle. La forme levée est construite en ajoutant un seul modificateur ? à chaque opérande et type de résultat. L'opérateur levé produit une valeur nulle si l'un des opérandes ou les deux sont NULL (une exception étant les opérateurs & et | du type bool?, Comme décrit au §7.10.3). Sinon, l'opérateur levé déballe les opérandes, applique l'opérateur sous-jacent et encapsule le résultat.

Le raisonnement est le suivant: vous êtes à penser à null pour un type nullable comme signifiant « Je ne sais pas ce que la valeur est. » Quel est le résultat de "Je ne sais pas" plus un? "Je ne sais pas." Ainsi, le résultat devrait être null.

+0

Votre logique est bien formulée, mais elle devrait vraiment faire exception. Pensez à + comme une manière syntaxiquement plus simple d'exécuter number.Plus (2). Il devrait certainement lancer une exception si le nombre est nul ou peut facilement provoquer un comportement inattendu. –

+0

Pire encore, si vous avez un nombre et ADD null, il deviendra nul. –

0

Malheureusement, ce n'est pas le cas. Le X dans x = X + 1 est nul comme dans la première ligne de sorte que vous ajoutez 1 à null, ce qui équivaut à null.

Comme il est un int nullable, vous pouvez utiliser x.HasValue pour vérifier si elle a une valeur, puis x.Value pour obtenir la valeur int réelle sur

2

Pourquoi vous attendez-vous le compilateur de le jeter comme int quand vous l'avez déclaré comme Nullable? Le compilateur fait ce que vous lui avez dit de faire et null +1 = null.

Vous devrez lancer un cast explicitement ou vérifier x.HasValue avant d'essayer d'ajouter un int.

5

Les valeurs nulles ne sont jamais réellement des références nulles. Ce sont toujours des références d'objets. Leurs classes internes remplacent les opérateurs == et =. Si elles sont comparées à null, elles renverront la valeur de la propriété HasValue.

+1

La première phrase est correcte. Les deux phrases du milieu sont incorrectes. Les valeurs nulles sont des références d'objet * jamais *. La structure nullable ne remplace * pas * l'opérateur d'égalité. Il n'y a rien de tel que le remplacement de l'opérateur d'affectation. La dernière phrase est correcte. –

+0

Vous avez raison - pas l'opérateur d'affectation, mais la conversion implicite d'un int. Ils sont certainement des opérateurs différents, mais à la fin, l'effet est le même. Merci d'avoir fait remarquer cela. – rusty

2

La raison est que le compilateur crée un opérateur « levé » pour les types nullables - dans ce cas, il est quelque chose comme:

public static int? operator +(int? a, int? b) 
{ 
    return (a == null || b == null) ? (int?)null : a.Value + b.Value 
} 

Je pense que si vous essayez d'affecter le résultat à un non Valeur nullable, le compilateur sera forcé d'utiliser la surcharge non nullable et convertir x en un int.

e.g. int i = x + 1; //throws runtime exception 
+0

réellement int i = x + 1 est une erreur. int i = (int) (x + 1) lancera une exception si x n'a pas de valeur. – Dolphin

0

Indépendamment de savoir si x est réellement jamais nul, ce n'est même pas le point.

Le point est, quand avez-vous déjà vu un NullReferenceException en essayant d'effectuer un ajout?

L'exemple suivant ne lance pas non plus un NullReferenceException et est parfaitement valide.

string hello = null; 
string world = "world"; 
string hw = hello+world; 

Vous n'obtenir un NullReferenceException si vous essayez d'accéder à un membre sur un objet qui est nul.

-1

int? ne peut jamais être nul parce que c'est une structure. Les structs vivent sur la pile et la pile ne gère pas bien le null.

Voir What is a NullPointerException, and how do I fix it?

En outre, les types nullables ont 2 propriétés très utiles: HasValue, valeur

Ce code:

 if (x != null) 
     { 
      return (int) x; 
     } 

Faut-être remaniée à ceci:

 if (x.HasValue) 
     { 
      return x.Value; 
     } 
+0

Ceci est complètement incorrect. Premièrement, les types de valeur ne "vivent pas sur la pile". Les types de valeur résident là où ils vivent, sur la pile ou sur le tas, selon les besoins du gestionnaire de mémoire. Deuxièmement, il est parfaitement légal d'avoir une référence nulle sur la pile. "string s = null;", il y a une référence nulle sur la pile, pas de problème. –

+1

J'apprécie la correction. Quand j'ai commencé en .NET je me souviens de faire ceci: DateTime x = null; et obtenir cette erreur "Le compilateur ne peut pas assigner de null à un type de valeur, null ne peut être assigné qu'à un type de référence, struct est un type de valeur." J'ai mal compris le message. L'erreur parle des limitations du type null-literal et pas du type value. Merci pour la gifle bien méritée dans la tête. – fremis

Questions connexes