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 '' et 'System.DateTime'

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.)

Était-ce utile?

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) est false, alors je dois retourner une valeur de type DateTime égal à myDateTime. S'il est true, 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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top