Pourquoi cela ne compile-t-il pas?
int? number = true ? 5 : null;
Le type d'expression conditionnelle ne peut pas être déterminé car il n'y a pas de conversion implicite entre 'int' et <null>
Pourquoi cela ne compile-t-il pas?
int? number = true ? 5 : null;
Le type d'expression conditionnelle ne peut pas être déterminé car il n'y a pas de conversion implicite entre 'int' et <null>
Réponses:
La spécification (§7.14) dit que pour l'expression conditionnelle b ? x : y
, il y a trois possibilités, soit x
et les y
deux ont un type et certaines bonnes conditions sont remplies, un seul de x
et y
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:
Si un seul de
x
ety
a un type, et les deuxx
ety
sont 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 x
un int
littéral, et y
est null
qui n'a pas de type et null
n'est pas implicitement convertible en int
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:
int? number = true ? (int?)5 : null;
Ici, nous sommes toujours dans le cas où un seul de x
et y
a un type. Notez qu'il n'a null
toujours pas de type, le compilateur n'aura aucun problème avec cela car (int?)5
et null
sont 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
x
a typeX
ety
a typeY
alors
Si une conversion implicite (§6.1) existe de
X
versY
, mais pas deY
versX
, alorsY
est le type de l'expression conditionnelle.Si une conversion implicite (§6.1) existe de
Y
versX
, mais pas deX
versY
, alorsX
est le type de l'expression conditionnelle.Sinon, aucun type d'expression ne peut être déterminé et une erreur de compilation se produit.
Voici x
de type int
et y
est 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.
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:
int? number = true ? 5 : (int?)null;
int? number = true ? 5 : null as int?;
int? number = true ? 5 : (int?)null;
et les int? number = true ? (int?)5 : null;
deux !! compilation Scratch, scratch
Comme d'autres l'ont mentionné, le 5 est un int
, et null
ne 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 : new int?();
int? num = true ? 5 : null as int?;
int? num = true ? 5 : (int?)null;
int? num = true ? (int?)5 : null;
int? num = true ? 5 as int? : null;
int? num = true ? new int?(5) : null;
De plus, partout où vous voyez int?
, vous pouvez également utiliser Nullable<int>
.
Dans C# 9
ce blog est désormais autorisé
Cible typée ?? et ?
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 type
int? result = b ? 0 : null; // nullable value type
Ou votre exemple:
// Allowed in C# 9.
int? number = true ? 5 : null;