2010-03-15 19 views
8

Doublons possibles:
Nullable types and the ternary operator. Why won’t this work?
Conditional operator assignment with nullable<value> types?Pourquoi l'opérateur conditionnel n'autorise-t-il pas correctement l'utilisation de "null" pour l'assignation aux types nullables?

Ce ne compilera pas, indiquant « type d'expression conditionnelle ne peut être déterminée parce qu'il n'y a pas de conversion implicite entre 'System.DateTime' et '' "

task.ActualEndDate = TextBoxActualEndDate.Text != "" ? DateTime.Parse(TextBoxActualEndDate.Text) : null; 

T ses œuvres très bien

if (TextBoxActualEndDate.Text != "") 
    task.ActualEndDate = DateTime.Parse(TextBoxActualEndDate.Text); 
else 
    task.ActualEndDate = null; 
+2

Pouvez-vous vous débarrasser des dépendances sur votre code, afin que nous puissions reproduire cela? Remplacez 'task.ActualEndDate' par une variable locale, par exemple. –

+1

'int? q = vrai? 3: null; ' – SLaks

Répondre

8

Cela ne fonctionne pas parce que le compilateur ne sera pas insérer une conversion implicite des deux côtés à la fois, et null exige une conversion implicite de devenir un type Nullable.

Au lieu de cela, vous pouvez écrire

task.ActualEndDate = TextBoxActualEndDate.Text != "" ? 
    DateTime.Parse(TextBoxActualEndDate.Text) : new DateTime?(); 

Cela ne nécessite qu'une seule conversion implicite (DateTime-DateTime?).

Vous pouvez jeter chaque côté gauche:

task.ActualEndDate = TextBoxActualEndDate.Text != "" ? 
    (DateTime?)DateTime.Parse(TextBoxActualEndDate.Text) : null; 

Cela nécessite également une seule conversion implicite.

+0

Vous devriez vraiment utiliser un DateTime.TryParse (TextBoxActualEndDate.Text, out someDateVar) là. Ne faites jamais confiance aux entrées pour vous fournir une chaîne analysable. – Tomas

+2

Oui, mais ce n'est pas mon code. – SLaks

+2

La validation se produit à quelques endroits avant cette analyse, et je préférerais maintenant une exception plutôt qu'une quand j'essayer d'insérer DateTime.Min dans la base de données. –

4

L'opérateur conditionnel ne regarde pas la valeur retournée. Il ne regarde que les valeurs auxquelles il est demandé de choisir entre: DateTime et null. Il ne peut pas les identifier comme des instances du même type (car null n'est pas un DateTime valide), d'où l'erreur. Vous et moi savons que Nullable<DateTime> pourrait faire le travail, mais l'opérateur conditionnel n'est pas autorisé à introduire des types "plus grands": il est uniquement autorisé à regarder les types des deux expressions qu'il choisit. (Merci à Aaronaught dans les commentaires pour clarifier ce point et un bel exemple de clarification.)

Pour contourner ce problème, donner à l'opérateur une indication par coulée DateTime:

TextBoxActualEndDate.Text != "" ? (DateTime?)(DateTime.Parse(TextBoxActualEndDate.Text)) : null; 
            ^^^^^^^^^^^ 
+2

Correctement correct (+1): 'DateTime.Parse' renvoie un' DateTime' (pas un 'Nullable '), qui est un type de valeur et n'a pas de conversion vers ou depuis 'null'. Le compilateur n'a pas la capacité d'introduire des types "plus grands" dans l'équation quand il essaie de résoudre l'expression, il ne peut fonctionner qu'avec les types qui sont réellement là. C'est la même raison que vous ne pouvez pas écrire 'Stream s = expr? new MemoryStream(): nouveau FileStream (...) '. – Aaronaught

+0

Aaronaught: grande explication - Je vais plier cela. – itowlson

0

La raison est que nulle est de type object donc vous devez jeter le bon type, comme celui-ci:

task.ActualEndDate = TextBoxActualEndDate.Text != "" ? 
    DateTime.Parse(TextBoxActualEndDate.Text) : ((DateTime?) null); 
0

la façon la plus correcte (OMI) est de le faire

task.ActualEndDate = TextBoxActualEndDate.Text != "" ? 
    (DateTime?)(DateTime.Parse(TextBoxActualEndDate.Text) : null); 

J'utilise fréquemment l'opérateur de collaçage nul de cette manière.

0

C'est l'erreur probablement que vous obtenez dans cette situation:

erreur CS0173: Type d'expression conditionnelle ne peut être déterminée parce qu'il n'y a pas de conversion implicite entre « » et « int »)

Le compilateur explique qu'il ne sait pas comment convertir null en DateTime.


Fix:

vous devez castexplicitly la expression qui peut retourner null au type nullable. Cela fonctionne

((DateTime?) null);