2010-11-27 13 views

Répondre

25

Le compilateur ignore le côté gauche en déterminant le type du côté droit. Alors, quand il essaie de déduire le type de

Int64.Parse(myOtherVar) == 0 ? null : Int64.Parse(myOtherVar) 

il le fait sans prêter attention au fait que le côté gauche est un long?. Pour déterminer le type du côté droit, il fait remarquer que

Int64.Parse(myOtherVar) 

est un long et essaie maintenant de voir si null est ou peut être converti implicitement à un long. Comme il ne peut pas, vous obtenez le message d'erreur que vous voyez.

De §7.14 de la spécification C#:

Une expression conditionnelle de la forme b ? x : y ....

Les deuxième et troisième opérandes, x et y, de la commande de l'opérateur du type ?: de l'expression conditionnelle.

(1) Si x est de type X et y est de type Y puis

a. Si une conversion implicite (§6.1) existe de X à Y, mais pas de Y à X, alors Y est le type de l'expression conditionnelle.

b. Si une conversion implicite (§6.1) existe de Y à X, mais pas de X à Y, alors X est le type de l'expression conditionnelle.

c. Sinon, aucun type d'expression ne peut être déterminé et une erreur de compilation se produit.

(2) Si seulement l'un des x et y a un type, et les deux x et y, de convertibles areimplicitly à ce type, alors qui est le type de l'expression conditionnelle.

(3) Sinon, aucun type d'expression ne peut être déterminé et une erreur de compilation se produit.

Notez que nous sommes dans la situation (2) où x est null et ne dispose pas d'un type et y est Int64.Parse(myOtherVar) et est de type long. Notez que x n'est pas implicitement convertible au type de y. Donc les deux (1) et (2) échouent ci-dessus et nous aboutissons à (3) ce qui entraîne l'erreur de compilation qui a inspiré votre question. Notez la conclusion implicite de ce qui précède que le côté gauche ne joue pas de rôle dans la détermination du type de droite.

Pour remédier à cette situation remplacer

Int64.Parse(myOtherVar) 

avec

(long?)Int64.Parse(myOtherVar) 

Maintenant, la raison pour laquelle

myVar = null; 

est correct où myVar est déclarée comme long? est parce que le compilateur sait qu'il est une conversion implicite de null à long?.

Enfin, Int64.Parse lancera si myOtherVar ne peut pas être analysé par un long. Notez que vous effectuez également l'analyse deux fois, ce qui est inutile. Un meilleur modèle est

long value; 
if(Int64.TryParse(myOtherVar, out value)) { 
    myVar = value == 0 ? null : (long?)value; 
} 
else { 
    // handle case where myOtherVar couldn't be parsed 
} 
+0

Bizarrement, Int64.Parse (myOtherVar) == 0? (long?) null: Int64.Parse (myOtherVar); travaux. –

+0

belle utilisation variable. –

+0

Cela serait vraiment bien s'il y avait quelque chose de similaire à une "valeur" dans un accesseur, où vous pourriez créer une variable temporaire dans l'instruction if. –

2

L'utilisation de votre opérateur renvoie un Int64, pas un nullable, en raison de la dernière partie de l'opérateur ternaire. Il peut fonctionner que si vous faites place:

long? myVar = Int64.Parse(myOtherVar) == 0 ? null : 
    (long?)Int64.Parse(myOtherVar); 

Alors que vous retournez un long? à la place, de sorte que le null n'a pas besoin d'être converti en Int64

En outre, vous convertissez la valeur deux fois dans votre code, inutilement (une fois pour tester, et une fois pour obtenir la valeur). Votre code pourrait être meilleur ainsi:

long? tempVar = Int64.Parse(myOtherVar); 
long? myVar = tempVar==0? null : tempVar; 
2

Je suis sûr que vous vouliez dire:

myVar = value == 0 ? null : (long?)value; 

au lieu de

myVar = value == 0 ? null : value; 

J'ai aimé l'utilisation de la 'out' variable. Merci.

0

Cela fonctionne:

long? myVar = (long?)myOtherVar == 0 ? null : (long?)myOtherVar; 

..pour ceux qui aiment des réponses courtes.

0

Le compilateur essaie d'évaluer les expressions de gauche à droite

long? myVar = Int64.Parse(myOtherVar) == 0 ? null : Int64.Parse(myOtherVar); 

méthode int64.parse retourner une valeur long pas une valeur à long nullable.donc il n'y a pas de conversion entre null et Int64.Parse(myOtherVar); Alors, essayez celui-ci

long? myVar = Int64.Parse(myOtherVar) == 0 ? (long?) null : Int64.Parse(myOtherVar); 

OU
long? myVar = Int64.Parse(myOtherVar) == 0 ? null : (long?) Int64.Parse(myOtherVar);