résultat de type avec opérateur conditionnel en C #
-
26-09-2019 - |
Question
Je suis en train d'utiliser l'opérateur conditionnel, mais je suis enferrons le type, il pense que le résultat devrait être.
est un exemple ci-dessous que j'ai trouvé le moyen de montrer la question que j'ai:
class Program
{
public static void OutputDateTime(DateTime? datetime)
{
Console.WriteLine(datetime);
}
public static bool IsDateTimeHappy(DateTime datetime)
{
if (DateTime.Compare(datetime, DateTime.Parse("1/1")) == 0)
return true;
return false;
}
static void Main(string[] args)
{
DateTime myDateTime = DateTime.Now;
OutputDateTime(IsDateTimeHappy(myDateTime) ? null : myDateTime);
Console.ReadLine(); ^
} |
} |
// This line has the compile issue ---------------+
Sur la ligne indiquée ci-dessus, je reçois l'erreur de compilation suivante:
Type d'expression conditionnelle ne peut être déterminée parce qu'il n'y a pas de conversion implicite entre '
Je suis confus parce que le paramètre est un type Nullable (DateTime?). Pourquoi at-il besoin de convertir du tout? Si elle est nulle puis utilisez que, si elle est un temps de date, utilisez alors que.
J'avais l'impression que:
condition ? first_expression : second_expression;
est la même que:
if (condition)
first_expression;
else
second_expression;
Il est clair que ce n'est pas le cas. Quel est le raisonnement derrière cela?
(REMARQUE:.? Je sais que si je fais « MyDateTime » DateTime nullable il fonctionnera Mais pourquoi est-il besoin
Comme je l'ai dit plus tôt c'est un exemple artificiel. Dans mon exemple concret « MyDateTime » est une valeur mappée de données qui ne peuvent pas être fait annulable.)
La solution
Le compilateur ne déduit pas le type du résultat de l'opérateur conditionnel de l'utilisation du résultat, mais des types de ses arguments. Le compilateur échoue lorsqu'il voit cette expression, car il ne peut pas déduire le type du résultat:
IsDateTimeHappy(myDateTime) ? null : myDateTime;
Depuis null
et DateTime
ne sont pas compatibles, vous devez dire au compilateur ce type doit être. Un casting devrait faire l'affaire:
DateTime? x = IsDateTimeHappy(myDateTime) ? (DateTime?)null : myDateTime;
OutputDateTime(x);
Maintenant, le compilateur aura aucun problème. Vous pouvez également écrire ci-dessus sur une ligne si vous préférez (mais je ne serais probablement pas le faire):
OutputDateTime(IsDateTimeHappy(myDateTime) ? (DateTime?)null : myDateTime);
Eric Lippert a bonne réponse qui est également ici et va dans plus de détails sur la façon dont le compilateur détermine les types.
Autres conseils
La raison en est l'opérateur ternaire attend à ce que les deux opérandes soient du même type. Le get tout opérateur élaboré avant d'être affecté à un résultat (dans ce cas passé dans une fonction), de sorte que le compilateur ne peut pas savoir ce que le type de résultat est.
IsDateTimeHappy(myDateTime) ? null : myDateTime
Dans le cas ci-dessus il n'y a pas de chemin de conversion entre null
et DateTime
. Dès que vous lancez un d'eux DateTime?
, le compilateur peut convertir l'autre:
IsDateTimeHappy(myDateTime) ? (DateTime?)null : myDateTime
//OR
IsDateTimeHappy(myDateTime) ? null : (DateTime?)myDateTime
La ligne de poing code ci-dessus fonctionne parce que le compilateur peut convertir DateTime
à DateTime?
via un opérateur de conversion implicite:
//In Nullable<T>
public static implicit operator T?(T value);
La deuxième ligne fonctionne parce que null
peut être affecté à DateTime?
puisque ce dernier est un type de référence.
La conversion implicite n'est pas autorisée par la déclaration de retour. Si vous aviez
if (condition)
return first_expression;
else
return second_expression;
Ensuite, vous seriez comparer des pommes avec des pommes. Et vous auriez pas de problèmes -. Comme vous l'avez dit
Dans votre cas, vous êtes alloué beaucoup d'espace sur la pile pour une DateTime - qui est un type de valeur non annulable. Donc, vous faites une déclaration qui ne fait pas de sens au compilateur. Si vous dites, je vais vous passer un A
ou un B
, le A
et B
doivent être la même chose. Dans votre cas, le B
ne peut jamais être un A
.
Je pense que cela a également répondu ici: types nullables et l'opérateur ternaire: pourquoi est-`? 10: null` interdit
L'espoir que ce que vous aviez besoin. =]
Qu'est-ce que le compilateur dit est:
Si
IsDateTimeHappy(myDateTime)
estfalse
, alors je dois retourner une valeur de typeDateTime
égal àmyDateTime
. S'il esttrue
, alors je dois retourner une valeur égale ànull
, mais vous ne me dites pas de quel type il devrait être!
Voilà pourquoi la réponse de Mark est la solution. Après avoir fourni un casting dire au compilateur quel type de valeur est retournée si la condition est true
, il peut vérifier si les (ou sont des) valeurs de retour de true
et false
peuvent être convertis au même type.
Vive Mark! ; -)
Au lieu d'utiliser null
default(DateTime?)
puis les deux côtés de la ternaires avoir des types compatibles.