В С# почему оператор условного оператора неявно не вводится в тип с нулевым значением
Мне любопытно, почему неявный листинг терпит неудачу в...
int? someValue = SomeCondition ? ResultOfSomeCalc() : null;
и почему я должен выполнить явное преобразование вместо
int? someValue = SomeCondition ? ResultofSomeCalc() : (int?)null;
Мне кажется, что у компилятора есть вся информация, необходимая для принятия неявного решения о литье, нет?
Ответы
Ответ 1
Соответствующий раздел спецификации С# 3.0 равен 7.13, условный оператор:
Второй и третий операнды оператора?: управляют типом условного выражения. Пусть X и Y - типы второго и третьего операндов. Тогда,
Если X и Y являются одним и тем же типом, то это тип условного
В противном случае, если неявное преобразование (§6.1) существует от X до Y, но не от Y до X, то Y является типом условного выражения.
В противном случае, если неявное преобразование (§6.1) существует от Y до X, но не от X до Y, то X является типом условного выражения.
В противном случае тип выражения не может быть определен, и возникает ошибка времени компиляции.
Ответ 2
Меня также раздражает, что он не может вывести тип, основанный на назначении, особенно когда он тип значения. Есть причины, когда вы попадаете в геральдические объекты.
Если "ResultOfSomeCalc()" вернул "int?", тогда это будет работать. С# нужно выяснить тип независимо от того, что находится слева от задания. Таким образом, вы говорите ему, что вы вернете нуль или int, и логики в компиляторе не существует, чтобы он заменил Nullable как общий знаменатель.
Обратите внимание, что эти варианты DO работают, и это может помочь вам понять:
object someValue = true ? new Nullable<int>(ResultOfSomeCalc()) : null;
object someValue = true ? (int?)ResultOfSomeCalc() : null;
Надеюсь, что это поможет.
Ответ 3
Кажется, что это то, что компилятор должен понять, но есть еще один способ сделать это, используя ключевое слово по умолчанию. Это может быть самый маленький бит, менее уродливый, чем приведение:
int? someValue = SomeCondition ? ResultofSomeCalc() : default(int?);
Это использование дефолта, похоже, не хорошо документировано, но работает. По крайней мере, это мешает вам помешать вашему коду волшебными значениями (я утверждаю, что null/zero/false/etc) действительно волшебные значения).
Ответ 4
См. также Почему этот код недействителен в С#?
Ответ 5
Если ваша функция ResultofSomeCalc() возвращает int? то это будет работать.
Если ваша функция возвращает int, компилятор выдает предупреждение: Тип условного выражения не может быть определен, потому что нет никакого неявного преобразования между 'int' и ''
Я предполагаю, что это то, что вы видите. Оба выражения в условном операторе "?:" Должны иметь один и тот же тип или должны быть конвертированы в один и тот же тип с помощью неявного литья.
Измените возвращаемый тип ResultOfSomeCalc на int?, или вам нужно будет иметь приведение в нулевое выражение.
Ответ 6
Сделайте свою функцию ResultOfSomeCalc() возвращаемым типом как nullabel int like (int?)
Int? someValue = (int?) SomeCondition? ResultofSomeCalc(): (int?) Null;