Ответ 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?
.