Почему null нужен явный тип приведения здесь?
Следующий код не компилируется:
//int a = ...
int? b = (int?) (a != 0 ? a : null);
Для компиляции его необходимо изменить на
int? b = (a != 0 ? a : (int?) null);
Поскольку оба b = null
и b = a
являются законными, для меня это не имеет смысла.
Почему нам нужно отбрасывать null
в int?
и почему мы не можем просто предоставить явный тип для всего выражения (что, как я знаю, возможно в других случаях)?
Ответы
Ответ 1
Из раздела 7.13 Спецификации языка С#:
Второй и третий операнды оператора?: управляют типом условного выражения. Пусть X и Y - типы второго и третьего операндов. Тогда,
- Если X и Y являются одним и тем же типом, то это тип условного выражения.
- В противном случае, если неявное преобразование (§6.1) существует из X в Y, но не от Y до X, то Y является типом условного выражения.
- В противном случае, если неявное преобразование (§6.1) существует от Y до X, но не от X до Y, то X является типом условного выражения.
- В противном случае тип выражения не может быть определен, и возникает ошибка времени компиляции.
В вашем случае нет никакого неявного преобразования из int в null или наоборот. Ваш бросок решает проблему, int преобразуется в int?
Ответ 2
Обе альтернативы оператора ?:
должны быть одного типа.
В противном случае компилятор не может вывести тип всего условного выражения.
null
не является int
, поэтому вам нужно дать подсказку компилятору, что результирующий тип int?
.
Изменить: как указывали другие, два типа не обязательно должны быть одинаковыми, но один из них должен быть привязан к другому (другой будет типом результата). Подробнее см. спецификации.
Ответ 3
Вы можете спасти себя от кастинга, если вы используете default(int?)
вместо null
.
int a = 42;
int? b = (a != 0 ? a : default(int?));
Ответ 4
потому что, когда вы используете такую нотацию, оба члена должны быть одного типа, поэтому вам нужно явно сказать "этот член является int?".
ясно?
Ответ 5
Когда вы используете условный оператор с операндами разных типов, компилятор проверяет, может ли один из типов быть неявным образом преобразован в другой тип.
Если ни один из типов не может быть неявно преобразован в другой, он выдаст ошибку, даже если есть третий тип, который они могут как неявно преобразовать. Компилятор не будет вставлять неявное преобразование с обеих сторон сразу.
В вашем случае как int
, так и null
требуется, чтобы неявные преобразования стали int?
, поэтому он не работает.
Вам нужно изменить код, чтобы одна сторона была int?
, а другая сторона была неявно преобразована в int?
. Простейший способ сделать это - заменить null
на new int?()
следующим образом:
int? b = (a != 0 ? a : new int?());
Для этого требуется только одно неявное преобразование (int
to int?
).
Ответ 6
Это почти дубликат одного моих вопросов относительно условного оператора. Это не нуль, это действительно :
.
Ответ, принятый там, довольно хорош, не кто иной, как Эрик Липперт, который находится в команде компилятора С#.