Je viens de tomber sur une erreur étrange:
private bool GetBoolValue()
{
//Do some logic and return true or false
}
Ensuite, dans une autre méthode, quelque chose comme ceci:
int? x = GetBoolValue() ? 10 : null;
Simple, si la méthode retourne true, attribuez 10 à Nullable int
x. Sinon, affectez null à nullable int. Cependant, le compilateur se plaint:
Erreur 1 Le type de l'expression conditionnelle ne peut pas être déterminé car il n'y a pas de conversion implicite entre
int
et<null>
.
Est-ce que je vais devenir fou?
Le compilateur essaie d'abord d'évaluer l'expression de droite:
GetBoolValue() ? 10 : null
Le 10
est un int
littéral (et non int?
) et null
est bien null
. Il n'y a pas de conversion implicite entre ces deux, d'où le message d'erreur.
Si vous modifiez l'expression de droite pour l'une des suivantes, elle est compilée car il existe une conversion implicite entre int?
et null
(# 1) et entre int
et int?
(N ° 2, n ° 3).
GetBoolValue() ? (int?)10 : null // #1
GetBoolValue() ? 10 : (int?)null // #2
GetBoolValue() ? 10 : default(int?) // #3
Essaye ça:
int? x = GetBoolValue() ? 10 : (int?)null;
Fondamentalement, ce qui se passe est que l'opérateur conditionnel est incapable de déterminer le "type de retour" de l'expression. Puisque le compilateur décide implicitement que 10
_ est un int
, il décide ensuite que le type de retour de cette expression doit également être un int
. Étant donné qu'un int
ne peut pas être null
(le troisième opérande de l'opérateur conditionnel), se plaint-il.
En convertissant le null
en un Nullable<int>
nous disons explicitement au compilateur que le type de retour de cette expression doit être un Nullable<int>
. Vous auriez pu tout aussi facilement lancer le 10
à int?
aussi et a le même effet.
Essaye ça:
int? result = condition ? 10 : default(int?);
Incidemment, l'implémentation Microsoft du compilateur C # obtient en fait l'analyse de type de l'opérateur conditionnel de manière très subtile et intéressante (pour moi). Mon article à ce sujet est Type inférence malheurs, première partie.
Essayez l'une de celles-ci:
int? x = GetBoolValue() ? (int?)10 : null;
int? x = GetBoolValue() ? 10 : (int?)null;
Le problème est que l'opérateur ternaire déduit le type en fonction de votre premier paramétrage ... 10 dans ce cas, qui est un int, pas un int nullable.
Vous pourriez avoir plus de chance avec:
int? x = GetBoolValue() (int?)10 : null;
Il suffit d'ajouter un casting explicite.
int? x = GetBoolValue() ? 10 : (int?)null;
C’est l’opérateur ternaire qui est confondu - le deuxième argument est un entier et le troisième argument examiné est lui aussi un entier, et la valeur null n’adapte pas.
C'est parce que le compilateur détermine le type de l'opérateur conditionnel par ses deuxième et troisième opérandes, et non par ce à quoi vous affectez le résultat. Il n'y a pas de conversion directe entre un entier et une référence null que le compilateur peut utiliser pour déterminer le type.
int? x = GetBoolValue() ? 10 : (int?)null;
La raison pour laquelle vous voyez cela est parce que vous utilisez Nullable dans les coulisses et que vous devez dire à C # que votre "null" est une instance nulle de Nullable.