Введите результат с условным оператором в C#

Я пытаюсь использовать условный оператор, но я становлюсь одержимым типом, он думает, что результат должен быть.

Ниже пример, что я умудрился показывать проблему, которую я имею:

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  ---------------+

На строке, обозначенной выше, я получаю следующую ошибку компиляции:

Тип условного выражения не может быть определен, потому что нет никакого неявного преобразования между' <пустой>' и 'Системой. DateTime'

Я смущен, потому что параметр является nullable типом (DateTime?). Почему это должно преобразовать вообще? Если это является пустым, затем используют это, если это - время даты, затем используют это.

У меня создалось впечатление что:

condition ? first_expression : second_expression;

совпал с:

if (condition)
   first_expression;
else
   second_expression;

Очевидно дело обстоит не так. Каково обоснование позади этого?

(ПРИМЕЧАНИЕ: Я знаю, что, если я делаю "myDateTime" nullable DateTime затем, он будет работать. Но почему этому нужен он?

Как я заявил ранее, это - изобретенный пример. В моем реальном примере "myDateTime" является отображенным значением данных, которое не может быть сделано nullable.)

11
задан Anthony Pegram 25 January 2011 в 19:01
поделиться

6 ответов

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

IsDateTimeHappy(myDateTime) ? null : myDateTime;

Поскольку null и DateTime несовместимы, вам необходимо сообщить компилятору, какой тип должно быть. Приведение должно помочь:

DateTime? x = IsDateTimeHappy(myDateTime) ? (DateTime?)null : myDateTime;
OutputDateTime(x);

Теперь у компилятора не будет проблем. Вы также можете написать вышеупомянутое в одной строке, если хотите (но я, вероятно, не стал бы этого делать):

OutputDateTime(IsDateTimeHappy(myDateTime) ? (DateTime?)null : myDateTime);

Эрик Липперт имеет хороший ответ , который также актуален здесь и более подробно описывает, как компилятор определяет типы.

22
ответ дан 3 December 2019 в 03:51
поделиться

Причина в том, что тернарный оператор ожидает, что оба операнда будут одного типа. Весь оператор отрабатывается ДО того, как он присваивается результату (в данном случае передается в функцию), поэтому компилятор не может знать, каков тип результата.

IsDateTimeHappy(myDateTime) ? null : myDateTime

В приведенном выше случае нет пути преобразования между null и DateTime. Как только вы приведете один из них к DateTime?, компилятор сможет преобразовать другой:

IsDateTimeHappy(myDateTime) ? (DateTime?)null : myDateTime
//OR
IsDateTimeHappy(myDateTime) ? null : (DateTime?)myDateTime

Первая строка кода выше работает, потому что компилятор может преобразовать DateTime в DateTime? через неявный оператор преобразования:

//In Nullable<T>
public static implicit operator T?(T value);

Вторая строка работает, потому что null может быть присвоен DateTime?, поскольку последний является ссылочным типом.

2
ответ дан 3 December 2019 в 03:51
поделиться

Неявное преобразование не разрешено оператором return. Если бы у вас было

if (condition)
    return first_expression;
else
    return second_expression;

, вы бы сравнивали яблоки с яблоками. И у вас не будет проблем - как вы заявили.

В вашем случае у вас выделено так много места в стеке для DateTime - типа значения, не допускающего значения NULL. Итак, вы делаете заявление, которое не имеет никакого смысла для компилятора. Если вы скажете, что я дам вам A или B , то A и B должны быть тоже самое. В вашем случае B никогда не может быть A .

1
ответ дан 3 December 2019 в 03:51
поделиться

Думаю, здесь тоже есть ответ: Обнуляемые типы и тернарный оператор: почему `? 10: null` запрещено?

Надеюсь, это то, что вам нужно. =]

1
ответ дан 3 December 2019 в 03:51
поделиться

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

Если IsDateTimeHappy (myDateTime) равно false , то мне нужно вернуть значение типа DateTime , равное на myDateTime . Если это истина , то мне нужно вернуть значение, равное null , но вы не сказали мне, какой это должен быть тип!

Вот почему ответ Марка - это решение. После того, как вы предоставите приведение, сообщающее компилятору, какой тип значения будет возвращен, если условие равно истина , он может проверить, могут ли возвращаемые значения истина и ложь быть преобразованы в (или имеют) один и тот же тип.

Ура, Марк! ; -)

0
ответ дан 3 December 2019 в 03:51
поделиться

Вместо null используйте default (DateTime?) , и тогда обе стороны тернарного элемента будут иметь совместимые типы.

0
ответ дан 3 December 2019 в 03:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: