La spécification (§7.14) dit que pour l'expression conditionnelle b ? x : y, il y a trois possibilités, soit xet les ydeux ont un type et certaines bonnes conditions sont remplies, un seul de xet ya un type et certaines bonnes conditions sont remplies, ou une erreur de compilation se produit. Ici, «certaines bonnes conditions» signifie que certaines conversions sont possibles, dont nous entrerons dans les détails ci-dessous.
Passons maintenant à la partie pertinente de la spécification:
Si un seul de xet ya un type, et les deux xet ysont implicitement convertibles en ce type, alors c'est le type de l'expression conditionnelle.
Le problème ici est que dans
int? number =true?5:null;
un seul des résultats conditionnels a un type. Voici xun intlittéral, et yest nullqui n'a pas de type et nulln'est pas implicitement convertible en int1 . Par conséquent, «certaines bonnes conditions» ne sont pas remplies et une erreur de compilation se produit.
Il y a deux façons de contourner cela:
int? number =true?(int?)5:null;
Ici, nous sommes toujours dans le cas où un seul de xet ya un type. Notez qu'il n'a nulltoujours pas de type, le compilateur n'aura aucun problème avec cela car (int?)5et nullsont tous deux implicitement convertibles en int?(§6.1.4 et §6.1.5).
L'autre façon est évidemment:
int? number =true?5:(int?)null;
mais maintenant nous devons lire une clause différente dans la spécification pour comprendre pourquoi c'est correct:
Si xa type Xet ya type Yalors
Si une conversion implicite (§6.1) existe de Xvers Y, mais pas de Yvers X, alors Yest le type de l'expression conditionnelle.
Si une conversion implicite (§6.1) existe de Yvers X, mais pas de Xvers Y, alors Xest le type de l'expression conditionnelle.
Sinon, aucun type d'expression ne peut être déterminé et une erreur de compilation se produit.
Voici xde type intet yest de type int?. Il n'y a pas de conversion implicite de int?à int, mais il y a une conversion implicite de intà int?donc le type de l'expression est int?.
1 : Notez en outre que le type du côté gauche est ignoré dans la détermination du type de l'expression conditionnelle, une source courante de confusion ici.
Bonne citation de la spécification pour illustrer pourquoi cela se produit - +1!
JerKimball
8
Une autre option est new int?()à la place de (int?)null.
Guvante
1
C'est également le cas si vous avez un type de champ de base de données Nullable, par exemple un DateTime Nullable et que vous essayez de convertir des données en DateTime, quand cela est nécessaire(DateTime?)
Mike Upjohn
73
null n'a aucun type identifiable - il a juste besoin d'un petit coup de pouce pour le rendre heureux:
Le problème n'est pas qu'il nulln'y ait pas de type identifiable. Le problème est qu'il n'y a pas de conversion implicite de nullvers int. Détails ici .
jason
la chose intéressante est que , int? number = true ? 5 : (int?)null;et les int? number = true ? (int?)5 : null;deux !! compilation Scratch, scratch
davidhq
2
Je couvre exactement pourquoi cela se produit dans ma réponse .
jason
4
Comme d'autres l'ont mentionné, le 5 est un int, et nullne peut pas être implicitement converti en int.
Voici d'autres moyens de contourner le problème:
int? num =true?5:default(int?);int? num =true?5:newint?();int? num =true?5:nullasint?;int? num =true?5:(int?)null;int? num =true?(int?)5:null;int? num =true?5asint?:null;int? num =true?newint?(5):null;
De plus, partout où vous voyez int?, vous pouvez également utiliser Nullable<int>.
Parfois conditionnel ?? et?: les expressions n'ont pas de type partagé évident entre les branches. De tels cas échouent aujourd'hui, mais C # 9.0 les autorisera s'il existe un type de cible vers lequel les deux branches sont converties:
Person person = student ?? customer;// Shared base typeint? result = b ?0:null;// nullable value type
Réponses:
La spécification (§7.14) dit que pour l'expression conditionnelle
b ? x : y
, il y a trois possibilités, soitx
et lesy
deux ont un type et certaines bonnes conditions sont remplies, un seul dex
ety
a un type et certaines bonnes conditions sont remplies, ou une erreur de compilation se produit. Ici, «certaines bonnes conditions» signifie que certaines conversions sont possibles, dont nous entrerons dans les détails ci-dessous.Passons maintenant à la partie pertinente de la spécification:
Le problème ici est que dans
un seul des résultats conditionnels a un type. Voici
x
unint
littéral, ety
estnull
qui n'a pas de type etnull
n'est pas implicitement convertible enint
1 . Par conséquent, «certaines bonnes conditions» ne sont pas remplies et une erreur de compilation se produit.Il y a deux façons de contourner cela:
Ici, nous sommes toujours dans le cas où un seul de
x
ety
a un type. Notez qu'il n'anull
toujours pas de type, le compilateur n'aura aucun problème avec cela car(int?)5
etnull
sont tous deux implicitement convertibles enint?
(§6.1.4 et §6.1.5).L'autre façon est évidemment:
mais maintenant nous devons lire une clause différente dans la spécification pour comprendre pourquoi c'est correct:
Voici
x
de typeint
ety
est de typeint?
. Il n'y a pas de conversion implicite deint?
àint
, mais il y a une conversion implicite deint
àint?
donc le type de l'expression estint?
.1 : Notez en outre que le type du côté gauche est ignoré dans la détermination du type de l'expression conditionnelle, une source courante de confusion ici.
la source
new int?()
à la place de(int?)null
.DateTime
, quand cela est nécessaire(DateTime?)
null
n'a aucun type identifiable - il a juste besoin d'un petit coup de pouce pour le rendre heureux:la source
int? number = true ? 5 : null as int?;
null
n'y ait pas de type identifiable. Le problème est qu'il n'y a pas de conversion implicite denull
versint
. Détails ici .int? number = true ? 5 : (int?)null;
et lesint? number = true ? (int?)5 : null;
deux !! compilation Scratch, scratchComme d'autres l'ont mentionné, le 5 est un
int
, etnull
ne peut pas être implicitement converti enint
.Voici d'autres moyens de contourner le problème:
De plus, partout où vous voyez
int?
, vous pouvez également utiliserNullable<int>
.la source
Dans
C# 9
ce blog est désormais autoriséOu votre exemple:
la source