web-dev-qa-db-fra.com

Problème de type nullable avec?: Opérateur conditionnel

Quelqu'un pourrait-il expliquer pourquoi cela fonctionne en C # .NET 2.0:

    Nullable<DateTime> foo;
    if (true)
        foo = null;
    else
        foo = new DateTime(0);

... mais cela ne veut pas:

    Nullable<DateTime> foo;
    foo = true ? null : new DateTime(0);

La dernière forme me donne une erreur de compilation "Le type de l'expression conditionnelle ne peut pas être déterminé car il n'y a pas de conversion implicite entre '<null>' et 'System.DateTime'".

Non pas que je ne puisse pas utiliser l'ancien, mais le second style est plus cohérent avec le reste de mon code.

152
Nick Gotch

Cette question a déjà été posée à maintes reprises. Le compilateur vous dit qu'il ne sait pas comment convertir null en DateTime.

La solution est simple:

DateTime? foo;
foo = true ? (DateTime?)null : new DateTime(0);

Notez que Nullable<DateTime> peut être écrit DateTime? qui vous épargnera beaucoup de frappe.

318
Stewart Johnson

FYI (Offtopic, mais astucieux et lié aux types nullable) nous avons un opérateur pratique pour les types nullable appelé l'opérateur de coalescence nul

??

Utilisé comme ceci:

// Left hand is the nullable type, righthand is default if the type is null.
Nullable<DateTime> foo;
DateTime value = foo ?? new DateTime(0);
18
FlySwat

C'est parce que dans un opérateur ternaire, les deux valeurs doivent être résolues en un même type.

8
MojoFilter

Je sais que cette question a été posée en 2008 et qu'elle est maintenant 5 ans plus tard, mais la réponse marquée comme une réponse ne me satisfait pas. La vraie réponse est que DateTime est une structure et qu’elle n’est pas compatible avec null. Vous avez deux façons de résoudre ce problème:

La première consiste à rendre null la compatibilité avec DateTime (par exemple, convertissez null en DateTime? Comme le suggère l'homme avec 70 votes positifs, ou attribuez la valeur null à Object ou à ValueType).

La seconde consiste à rendre le DateTime compatible avec null (par exemple, convertissez DateTime en DateTime?).

3
Mishax

Une autre solution similaire à celle acceptée consiste à utiliser le mot-clé default de C #. Bien que défini à l'aide de génériques, il est en fait applicable à tout type.

Exemple d'utilisation appliqué à la question du PO:

Nullable<DateTime> foo;
foo = true ? default(DateTime) : new DateTime(0);

Exemple d'utilisation avec la réponse acceptée actuelle:

DateTime? foo;
foo = true ? default(DateTime) : new DateTime(0);

De plus, en utilisant default, vous n'avez pas besoin de spécifier la variable sous la forme nullable pour lui attribuer une valeur null. Le compilateur assignera automatiquement la valeur par défaut du type de variable spécifique et aucune erreur ne sera rencontrée. Exemple:

DateTime foo;
foo = true ? default(DateTime) : new DateTime(0);
3
newfurniturey