Условный оператор?: С отличным типом
Из документации MSDN следующие два фрагмента равны:
bool value;
int x = (value) ? 0 : 1;
и
bool value;
int x;
if (value)
x = 0;
else
x = 1;
Отличный, замечательный. Я использую это все время. Тесный и эффективный.
Если мы попробуем это с нулевым типом, например:
int? x = (value.HasValue) ? value.Value : null;
Мы получаем ошибку времени компиляции:
The type of conditional expression cannot be determined
because there is no implicit conversion between '{NullableType}' and null.
Это компилируется отлично:
int? value;
int? x;
if (value.HasValue)
x = value.Value;
else
x = null;
Итак, я понимаю, что для компиляции первого оператора компилятор требует явного перевода на (int?)null
. Я не понимаю, почему это требуется в этом выражении, но не в блоке If Else
.
Ответы
Ответ 1
null
может представлять любой тип данных на основе объектов. Вам нужно указать null
как тип данных, чтобы он знал, о чем вы говорите.
int? x = (value.HasValue) ? value.Value : (int?)null;
Я знаю, это звучит немного странно.
Чтобы ответить на вопросы в комментариях:
Почему это не подразумевается, хотя?
Да, я понимаю. Но почему мне не нужно бросать его в блок If Else?
Пропустить через код.
Ваш оператор else
выглядит следующим образом:
else x = null;
Это означает, что вы назначаете значение null
на x
. Это справедливо, поскольку x
является int?
, который принимает nulls
.
Разница возникает, когда у вас есть тернарный оператор. В нем говорится: "присвойте значение оператора в x
". Вопрос (и причина вашей ошибки) заключается в том, какой тип данных является результатом тернарного оператора?
Из вашего кода вы не можете быть уверены, и компилятор поднимает руки вверх.
int? x = (value.HasValue) ? value.Value : null;
// int? bool int ??
Какой тип данных null
? Вы быстро можете сказать "хорошо это a int?
, потому что другая сторона - это int
, а результат - int?
". Проблема заключается в следующем:
string a = null;
bool? b = null;
SqlConnectionStringBuilder s = null;
Это также верно, что означает, что null
можно использовать для any object-based datatype
. Вот почему вы должны явно использовать null
как тип, который хотите использовать, потому что он может быть использован для чего угодно!
Другое объяснение (и возможно более точное):
Вы не можете иметь неявный бросок между значением NULL и значением, отличным от нуля.
int
не является нулевым (это структура), где null
is. Вот почему в ответе Хабиба вы можете поставить бросок на левую или правую сторону.
Ответ 2
Для Конд. оператор MSDN:
Любой тип выражения first_expression и second_expression должен быть то же или неявное преобразование должно существовать от одного типа до другой.
Итак, в вашем случае ваше первое выражение и второе выражение:
int? x = (value.HasValue) ? value.Value : null;
^^^^^^^^ ^^^^^
first exp 2nd Exp
Теперь, если вы видите, ваше первое выражение имеет тип int
, а второе выражение null
, и оба они не одинаковы, и нет никакого неявного преобразования. Итак, кастинг любого из них на `int? решает проблему.
Итак:
int? x = (value.HasValue) ? (int?) value.Value : null;
или
int? x = (value.HasValue) ? value.Value : (int?) null;
в порядке.
Теперь почему это не требуется с if-else
, потому что здесь задействовано несколько операторов, и это не один оператор, присваивающий значение.
Ответ 3
var x = value.HasValue ? value.Value : default(int?);
работает тоже.
Ответ 4
Документация для оператора?: указывает, что тип выражения b? x: y определяется путем изучения типов x и y:
- Если X и Y являются одним и тем же типом, то это тип условного выражения.
- В противном случае, если неявное преобразование (раздел 6.1) существует от X до Y, но не от Y до X, то Y является типом условного выражения.
- В противном случае, если неявное преобразование (раздел 6.1) существует от Y до X, но не от X до Y, тогда X является типом условного выражения.
- В противном случае тип выражения не может быть определен, и возникает ошибка времени компиляции.
В вашем примере
int? x = (value.HasValue) ? value.Value : null;
нет никакого неявного преобразования между int и null, поэтому применяется последняя марка.
Ответ 5
Причина в том, что тип условного выражения определяется вторым и третьим операторами условного оператора (?:).
Так как null не имеет типа, компилятор не может определить тип общего выражения, поэтому он испускает ошибку компилятора.
Причина, по которой он работает с простым оператором присваивания (=), состоит в том, что левая часть оператора определяет тип. Поскольку в инструкции If тип x уже известен, компилятор не жалуется.
Дополнительные пояснения см. в разделе 7.14 (Условный оператор) и разделе 7.17.1 (Простое назначение).