Вопрос:

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

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

1122 просмотра

6 ответа

36179 Репутация автора

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

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

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 Источник Размещён: 11.05.2010 11:01

Ответы (6)


1 плюс

17582 Репутация автора

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

if (condition)
    return first_expression;
else
    return second_expression;

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

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

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

22 плюса

632906 Репутация автора

Решение

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

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 плюса

55989 Репутация автора

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

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

0 плюса

362114 Репутация автора

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

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

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

Ура Марк! ;-)

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

1 плюс

146 Репутация автора

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

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

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

0 плюса

4731 Репутация автора

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

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