234 votes

Le type d'expression conditionnelle ne peut ê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 être déterminé car il n'y a pas de conversion implicite entre 'int' et <null>.

438voto

Jason Points 125291

La spécification (§7.14) indique que pour une expression conditionnelle b ? x : y il y a trois possibilités, soit x y y Les deux ont un type y certains bonnes conditions sont remplies, seule une des x y y a un type y certains bonnes conditions sont respectées, ou une erreur de compilation se produit. Ici, "certaines bonnes conditions" signifie que certaines conversions sont possibles, ce que nous détaillerons plus loin.

Passons maintenant à la partie pertinente de la spécification :

Si un seul des x y y a un type, et les deux x y y sont implicitement convertibles en ce type, alors c'est le type de l'expression conditionnelle.

Le problème ici est qu'en

int? number = true ? 5 : null;

un seul des résultats conditionnels a un type. Ici, x est un int littéral, et y est null qui fait pas ont un type y null n'est pas implicitement convertible en un int 1 . Par conséquent, "certaines bonnes conditions" ne sont pas remplies, et une erreur de compilation se produit.

Il y a sont Deux façons de contourner ce problème :

int? number = true ? (int?)5 : null;

Ici, nous sommes toujours dans le cas où un seul des éléments suivants x y y a un type. Notez que null toujours n'a pas de type mais le compilateur n'aura pas de problème avec cela car (int?)5 y null sont toutes deux implicitement convertibles en int? (§6.1.4 et §6.1.5).

L'autre voie est évidente :

int? number = true ? 5 : (int?)null;

mais maintenant nous devons lire un différents dans la spécification pour comprendre pourquoi cela est acceptable :

Si x a un type X y y a un type Y puis

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

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

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

Aquí x est de type int y y est de type int? . Il n'y a pas de conversion implicite de int? a int mais il y a une conversion implicite de int a int? donc le type de l'expression est int? .

1 : Notez en outre que le type du côté gauche est ignoré pour déterminer le type de l'expression conditionnelle, ce qui est une source fréquente de confusion ici.

4 votes

Bonne citation de la spécification pour illustrer pourquoi cela se produit - +1 !

10 votes

Une autre option est new int?() à la place de (int?)null .

1 votes

C'est également le cas si vous disposez d'un champ de base de données de type nullable, par exemple un DateTime nullable, et que vous essayez de convertir des données en format DateTime alors qu'il fallait en fait (DateTime?)

96voto

Marc Gravell Points 482669

null n'a pas de type identifiable - il a juste besoin d'un petit coup de pouce pour être heureux :

int? number = true ? 5 : (int?)null;

5 votes

Ou vous pouvez faire int? number = true ? 5 : null as int?;

1 votes

Belle réponse qui va droit au but. Bonne lecture connexe : ericlippert.com/2013/05/30/qu'est-ce que cela signifie ?

0 votes

La question est no que null n'a pas de type identifiable. Le problème est qu'il n'y a pas de conversion implicite de null a int . Détails aquí .

16voto

WBuck Points 868

Sur C# 9 ceci est maintenant autorisé blog

La cible a tapé ? ? et ?

Parfois, les expressions conditionnelles ? ? et ? : 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 cible vers lequel les deux branches se convertissent :

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;

1 votes

Comme il se doit +1

8voto

Andrew Points 6859

Comme d'autres l'ont mentionné, le 5 est un int y null ne peut pas être implicitement converti en int .

Voici d'autres moyens de contourner ce 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;

Aussi, partout où vous voyez int? vous pouvez également utiliser Nullable<int> .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X