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

c# type-conversion nullable ternary-operator conditional-operator

1122 просмотра

6 ответа

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

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

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

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

Тип условного выражения не может быть определен, поскольку не существует неявного преобразования между «» и «System.DateTime»

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

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

condition ? first_expression : second_expression;

было так же, как:

if (condition)
   first_expression;
else
   second_expression;

Очевидно, это не тот случай. В чем причина этого?

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

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

Автор: Vaccano Источник Размещён: 13.11.2019 11:33

Ответы (6)


22 плюса

Решение

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

IsDateTimeHappy(myDateTime) ? null : myDateTime;

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

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

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

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

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

Автор: Mark Byers Размещён: 11.05.2010 11:06

2 плюса

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

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?поскольку последняя является ссылочным типом.

Автор: Igor Zevaka Размещён: 11.05.2010 11:08

1 плюс

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

if (condition)
    return first_expression;
else
    return second_expression;

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

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

Автор: Jarrett Meyer Размещён: 11.05.2010 11:04

1 плюс

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

Надеюсь, это то, что вам нужно. знак равно

Автор: iffy Размещён: 11.05.2010 11:11

0 плюса

Что говорит компилятор:

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

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

Ура Марк! ;-)

Автор: Jon Размещён: 11.05.2010 11:08

0 плюса

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

Автор: statenjason Размещён: 11.05.2010 11:12
Вопросы из категории :
32x32