Подтвердить что ты не робот

Почему допустимо "длинное значение" равным нулю?

Когда я отлаживал несколько строк кода и спрашивал, почему на земле это не работает, я наткнулся на эту ситуацию...

if(answer.AnswerID == null) 
{
    // do something
}

Если на самом деле это должно быть так:

if(answer == null)
{
    // do something
}
  • answer - объект типа Answer - a class.
  • AnswerID является свойством типа long.

Странно то, что если вы попробуете что-то вроде этого:

long myLongValue = null;

Компилятор покажет вам ошибку:

Connot convert null to long ...

Итак, мой вопрос: почему я не получил ошибку , когда я пытался сравнить long type с null?

отредактированы

Этот вопрос НЕ о nullable типах.

Я спрашиваю, почему .NET позволяет мне сравнивать длинную переменную с нулем. Я говорю о long type, а не о long? type.

4b9b3361

Ответ 1

Как отметил @Tim, вы не получите ошибку для следующего кода:

long foo = 42;

if (foo == null) { }

Вместо этого вы получите предупреждение:

Результат выражения всегда "false", поскольку значение типа "long" никогда не равно "null" типа "long?".

Это дает предупреждение вместо ошибки из-за отмененных операторов, определенных в спецификации языка С# как таковых:

Поднятые операторы разрешают предопределенные и определяемые пользователем операторы, которые работают с типами, не допускающими нулевое значение, которые также должны использоваться с типами NULL для этих типов. [...] Для операторов равенства

==  !=

существует допустимая форма оператора, если типы операндов являются неинифицируемыми типами значений, и если тип результата равен bool. Поднятая форма строится путем добавления сингла? модификатора для каждого типа операнда. Принятый оператор считает два нулевых значения равными, а нулевое значение не равно любому ненулевому значению. Если оба операнда не равны нулю, снятый оператор разворачивает операнды и применяет основной оператор для получения результата bool.

"Основной оператор" в этом случае предопределенный тип значения long == operator:

Для предопределенных типов значений оператор равенства (==) возвращает true, если значения его операндов равны, в противном случае - false.

Потому что foo неявно преобразуется ( "Предопределенные неявные преобразования, которые работают с типами, отличными от нулевых значений, также могут использоваться с нулевыми формами этих типов." ) и литерал null также неявно преобразуются ( "Неявный преобразование существует из нулевого литерала в любой тип с нулевым значением." ), выражение:

(long)foo == null

становится:

(long?)foo == (long?)null

Что, если foo имеет тип long и, следовательно, всегда имеет значение, всегда возвращает false и даже не применяет оператор long ==.

Я не совсем уверен, но я подозреваю, что это существует, чтобы обеспечить сопоставление значений с нулевым и непустым значением без явного каста:

long? foo = 42;
long bar = 42;

Console.WriteLine(foo == bar); // true

foo = null;
Console.WriteLine(bar == foo); // false

Если это не было обработано языком, как указано выше, вы получите "Оператор == не может применяться к операндам типа long? и long", потому что Nullable<T> не имеет оператора ==, а long не имеет оператора ==, принимающего long?.

Ответ 2

Он будет компилироваться, и он будет выполняться, потому что компилятор оценивает == и продвигает long в long?, потому что это самое близкое соответствие с существующей реализацией ==.

Это действительно не лучшее из поведения, это похоже на VB: -)

Ответ 3

long получил коробку, и условие всегда было false.

long l = 0;
Console.WriteLine(l == null); //false

Это должно дать вам предупреждение:

Результат выражения всегда "false", поскольку значение типа "long" никогда не равно "null" типа "long?".

Resharper также предупреждает об этом. Это всегда ошибка, возможно, реликвия неудачного рефакторинга.

Ответ 4

Посмотрите здесь для получения информации о типах с нулевым значением. Обычные типы значений, такие как long и int, не могут быть сделаны обычными.

Причина, по которой она не сработала, когда вы пытались сравнить ее с нулевым, заключалась в том, что она выполняла сравнение, и она не была нулевой. Так что ошибок нет.