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 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
xetya un type, et les deuxxetysont 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 null toujours 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 typeXetya typeYalors
Si une conversion implicite (§6.1) existe de
XversY, mais pas deYversX, alorsYest le type de l'expression conditionnelle.Si une conversion implicite (§6.1) existe de
YversX, mais pas deXversY, alorsXest 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.
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 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 : 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# 9ce 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;