Неверные типы и тернарный оператор: почему? 10: null` запрещено?
Я натолкнулся на странную ошибку:
private bool GetBoolValue()
{
//Do some logic and return true or false
}
Затем в другом методе что-то вроде этого:
int? x = GetBoolValue() ? 10 : null;
Простой, если метод возвращает true, назначьте 10 Nullable int
x. В противном случае присвойте null тегу nullable. Однако компилятор жалуется:
Ошибка 1 Тип условного выражения не может быть определен, потому что нет никакого неявного преобразования между int
и <null>
.
Я иду с ума?
Ответы
Ответ 1
Сначала компилятор пытается оценить правильное выражение:
GetBoolValue() ? 10 : null
10
- это буква int
(не int?
) и null
, ну, null
. Там нет неявного преобразования между этими двумя, следовательно, сообщение об ошибке.
Если вы измените правое выражение на одно из следующих, то оно скомпилируется, потому что существует неявное преобразование между int?
и null
(# 1) и между int
и int?
(# 2, # 3).
GetBoolValue() ? (int?)10 : null // #1
GetBoolValue() ? 10 : (int?)null // #2
GetBoolValue() ? 10 : default(int?) // #3
Ответ 2
Попробуйте следующее:
int? x = GetBoolValue() ? 10 : (int?)null;
В основном то, что происходит, заключается в том, что условный оператор не может определить "возвращаемый тип" выражения. Поскольку компилятор решительно решает, что 10
является int
, тогда он решает, что возвращаемый тип этого выражения также должен быть int
. Поскольку int
не может быть null
(третий операнд условного оператора), он жалуется.
Отбрасывая null
на a Nullable<int>
, мы явно говорим компилятору, что возвращаемый тип этого выражения должен быть Nullable<int>
. Вы могли бы так же легко отличить 10
до int?
и иметь тот же эффект.
Ответ 3
Попробуйте следующее:
int? result = condition ? 10 : default(int?);
Ответ 4
Кстати, реализация Microsoft С# -компилятора фактически делает анализ типов условного оператора неправильным в очень тонком и интересном для меня способом. Моя статья о нем Ошибки вывода типа, часть первая.
Ответ 5
Попробуйте выполнить одно из следующих действий:
int? x = GetBoolValue() ? (int?)10 : null;
int? x = GetBoolValue() ? 10 : (int?)null;
Ответ 6
Проблема заключается в том, что тернарный оператор выводит тип, основанный на первом назначении параметра... 10 в этом случае, который является int, а не nullable int.
Вам может быть повезло больше:
int? x = GetBoolValue() (int?)10 : null;
Ответ 7
int? x = GetBoolValue() ? 10 : (int?)null;
Причина, по которой вы видите это, заключается в том, что за кулисами вы используете Nullable, и вам нужно сообщить С#, что ваш "null" является нулевым экземпляром Nullable.
Ответ 8
Просто добавьте эксликс.
int? x = GetBoolValue() ? 10 : (int?)null;
Это тройной оператор, который запутывается - второй аргумент является целым числом, и поэтому третий аргумент рассматривается как целое число, а null не подходит.
Ответ 9
Это потому, что компилятор определяет тип условного оператора по его второму и третьему операндам, а не по тому, что вы присваиваете результат. Между целочисленным значением и нулевой ссылкой нет прямого преобразования, которое компилятор может использовать для определения типа.