Почему не удается присвоить значение null в тернарном операторе: нет неявного преобразования между null и int? - PullRequest
11 голосов
/ 27 ноября 2010

Сбой с There is no implicit conversion between 'null' and 'int'

long? myVar = Int64.Parse( myOtherVar) == 0 ? null : Int64.Parse( myOtherVar);

Однако, это успешно:

if( Int64.Parse( myOtherVar) == 0)
    myVar = null;
else
    myVar = Int64.Parse( myOtherVar);

Есть ли способ добиться успеха троичного оператора?

Ответы [ 5 ]

25 голосов
/ 27 ноября 2010

Компилятор игнорирует левую сторону, когда выясняет тип правой стороны.Поэтому, когда он пытается вывести тип

Int64.Parse(myOtherVar) == 0 ? null : Int64.Parse(myOtherVar)

, он делает это, не обращая никакого внимания на тот факт, что левая часть - long?.Чтобы определить тип правой стороны, он отмечает, что

Int64.Parse(myOtherVar)

является long, и теперь пытается выяснить, может ли null неявно быть преобразовано в long.Так как это невозможно, вы получаете сообщение об ошибке, которое видите.

Из § 7.14 спецификации C #:

Условное выражение в форме b ? x : y ....

Второй и третий операнды x и y оператора ?: управляют типом условного выражения.

(1) Если x имеет тип X, а y имеет тип Y, то

a.Если неявное преобразование (§6.1) существует от X до Y, но не от Y до X, тогда Y является типом условного выражения.

b.Если неявное преобразование (§6.1) существует от Y до X, но не от X до Y, тогда X является типом условного выражения.

c.В противном случае тип выражения не может быть определен, и возникает ошибка времени компиляции.

(2) Если только один из x и y имеет тип и оба x и y, из которых можно явно преобразовать в этот тип, то это тип условного выражения.

(3) В противном случае тип выражения не может быть определен, и возникает ошибка времени компиляции.

Обратите внимание, что мы находимся в ситуации (2), где x равно null и не имеет типа, а y равно Int64.Parse(myOtherVar) и имеет тип long.Обратите внимание, что x неявно преобразуется в тип y.Поэтому оба (1) и (2) не выполняются выше, и мы получаем (3), что приводит к ошибке времени компиляции, которая вдохновила ваш вопрос. Обратите внимание на неявный вывод из вышесказанного, что левая сторона не играет роли в определении типа правой стороны.

Чтобы исправить это, замените

Int64.Parse(myOtherVar)

с

(long?)Int64.Parse(myOtherVar)

Теперь, причина, по которой

myVar = null;

в порядке, где myVar объявлен как long?, заключается в том, что компилятор знает, что существует неявное преобразование изnull до long?.

Наконец, Int64.Parse сгенерирует, если myOtherVar не может быть проанализирован с long.Обратите внимание, что вы также выполняете анализ дважды, что не нужно.Лучшая модель

long value;
if(Int64.TryParse(myOtherVar, out value)) {
    myVar = value == 0 ? null : (long?)value;
}
else {
    // handle case where myOtherVar couldn't be parsed
}
2 голосов
/ 27 ноября 2010

Я уверен, что вы хотели сказать:

  myVar = value == 0 ? null : (long?)value;

вместо

  myVar = value == 0 ? null : value;

Мне понравилось использование переменной 'out'.Спасибо.

2 голосов
/ 27 ноября 2010

Использование вашего оператора возвращает Int64, а не nullable, из-за последней части троичного оператора.Это может сработать, если вы сделаете вместо этого:

long? myVar = Int64.Parse( myOtherVar) == 0 ? null :
   (long?)Int64.Parse( myOtherVar);

Так что вместо этого вы возвращаете long?, поэтому null не нужно преобразовывать в Int64

Кроме того, вы конвертируете значение дважды в своем коде, без необходимости (один раз для тестирования и один раз для получения значения).Ваш код может быть лучше, таким образом:

long? tempVar = Int64.Parse(myOtherVar);
long? myVar = tempVar==0? null : tempVar;
0 голосов
/ 20 ноября 2015

Компилятор пытается оценить выражения слева направо

long? myVar = Int64.Parse( myOtherVar) == 0 ? null : Int64.Parse( myOtherVar);
Метод

int64.parse возвращает значение long, а не значение nullable long. поэтому нет конверсии между null и Int64.Parse( myOtherVar); Итак, попробуйте этот

long? myVar = Int64.Parse(myOtherVar) == 0 ? (long?) null : Int64.Parse(myOtherVar);

OR
long? myVar = Int64.Parse(myOtherVar) == 0 ? null : (long?) Int64.Parse(myOtherVar);

0 голосов
/ 07 октября 2015

Это будет работать:

long? myVar = (long?)myOtherVar == 0 ? null : (long?)myOtherVar;

.. для тех, кто любит короткие ответы.

...