.Net 2+:почему if( 1 == null ) больше не выдает исключение компилятора?

StackOverflow https://stackoverflow.com/questions/62606

Вопрос

Я использую int в качестве примера, но это применимо к любому типу значения в .Net

В .Net 1 следующее вызвало бы исключение компилятора:

int i = SomeFunctionThatReturnsInt();

if( i == null ) //compiler exception here

Теперь (в .Net 2 или 3.5) это исключение исчезло.

Я знаю, почему это так:

int? j = null; //nullable int

if( i == j )   //this shouldn't throw an exception

Проблема в том, что из-за int? обнуляется и int теперь имеет неявное приведение к int?.Приведенный выше синтаксис - это магия компилятора.На самом деле мы делаем:

Nullable<int> j = null; //nullable int

//compiler is smart enough to do this
if( (Nullable<int>) i == j)   

//and not this
if( i == (int) j)

Итак, теперь, когда мы делаем i == null мы получаем:

if( (Nullable<int>) i == null )

Учитывая, что C # в любом случае выполняет логику компилятора для вычисления этого, почему он не может быть достаточно умен, чтобы не делать этого при работе с абсолютными значениями, такими как null?

Это было полезно?

Решение

Я не думаю, что это проблема компилятора как таковой;целочисленное значение никогда не бывает нулевым, но идея их приравнивания не является недопустимой;это допустимая функция, которая всегда возвращает false.И компилятор знает;код

bool oneIsNull = 1 == null;

компилируется, но выдает предупреждение компилятора: The result of the expression is always 'false' since a value of type 'int' is never equal to 'null' of type '<null>'.

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

Другие советы

Странно ...компилирую это с помощью VS2008, ориентируясь на .NET 3.5:

static int F()
{
    return 42;
}

static void Main(string[] args)
{
    int i = F();

    if (i == null)
    {
    }
}

Я получаю предупреждение компилятора

warning CS0472: The result of the expression is always 'false' since a value of type 'int' is never equal to 'null' of type 'int?'

И это генерирует следующий IL ...который, предположительно, JIT оптимизирует

L_0001: call int32 ConsoleApplication1.Program::F()
L_0006: stloc.0 
L_0007: ldc.i4.0 
L_0008: ldc.i4.0 
L_0009: ceq 
L_000b: stloc.1 
L_000c: br.s L_000e

Можете ли вы опубликовать фрагмент кода?

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

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

Предупреждение 1 Результатом выражения всегда является 'false', поскольку значение типа 'int' никогда не равно 'null' типа 'int?'

Предупреждение новое (3.5, я думаю) - ошибка такая же, как если бы я сделал 1 == 2, что он достаточно умен, чтобы признать как никогда верным.

Я подозреваю, что при полной оптимизации 3.5 все утверждение будет просто удалено, так как оно довольно умное и никогда не дает истинных оценок.

В то время как я, возможно, захочу 1==2 для компиляции (например, для отключения функционального блока, пока я тестирую что-то еще) Я не хочу 1==null Для.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top