Неверный тип проблемы с?: Условный оператор

Может кто-нибудь объяснить, почему это работает в С#.NET 2.0:

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

... но это не так:

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

Последняя форма дает мне ошибку компиляции. "Тип условного выражения не может быть определен, потому что нет никакого неявного преобразования между" <null> "; и" System.DateTime".

Не то, чтобы я не мог использовать первое, но второй стиль более соответствует остальной части моего кода.

Ответ 1

Этот вопрос задавали уже несколько раз. Компилятор сообщает вам, что он не знает, как преобразовать null в DateTime.

Решение прост:

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

Обратите внимание, что Nullable<DateTime> может быть записано DateTime?, что спасет вас от набора символов.

Ответ 2

FYI (Offtopic, но отличный и связанный с типами NULL), мы имеем удобный оператор только для типов с нулевым значением, называемый нулевым коалесцирующим оператором

??

Используется следующим образом:

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

Ответ 3

Это потому, что в тернарном операторе два значения должны быть разрешены для одного и того же типа.

Ответ 4

Другим решением, аналогичным принятому, является использование ключевого слова С# default. Хотя он определен с использованием дженериков, он действительно применим к любому типу.

Пример использования приложения к вопросу OP:

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

Пример использования с текущим принятым ответом:

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

Кроме того, используя default, вам не нужно указывать переменную как nullable, чтобы присвоить ей значение null. Компилятор автоматически назначит значение по умолчанию для определенного типа переменной, и никакая ошибка не будет встречена. Пример:

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

Ответ 5

Я знаю, что этот вопрос был задан в 2008 году, а сейчас 5 лет спустя, но ответ, отмеченный как ответ, не удовлетворяет меня. Реальный ответ заключается в том, что DateTime является структурой, а в качестве структуры он несовместим с нулем. У вас есть два способа решить это:

Сначала нужно сделать null совместимым с DateTime (например, отбрасывать null до DateTime? как говорит джентльмен с 70 upvotes или отличать null от Object или ValueType).

Во-вторых, сделать DateTime совместимым с нулевым (например, придать DateTime DateTime?).