2013-06-18 6 views
11

Почему integer == null действительное булевское выражение в C#, если integer (переменная типа int) не допускает ошибки? (Я не против этого, на самом деле мне это нравится, но я не знаю, что это было возможно)Почему integer == null является допустимым булевым выражением в C#?

+1

Вы получаете предупреждение, что-то вроде строк «выражение всегда ложно». Что касается того, почему это * разрешено *, то есть не приводит к ошибке времени компиляции ... Я полагаю, что по той же причине это разрешено; 'while (true)' –

+0

Компилятор C# во время компиляции оптимизирует это значение false при компиляции в режиме деблокирования ('ldc.i4.0' заканчивается тем, что находится в IL). – vcsjones

+1

Возможный дубликат [C# okay с сопоставлением типов значений с нулевым] (http://stackoverflow.com/questions/1972262/c-sharp-okay-with-comparing-value-types-to-null) –

ответ

19

Хотя int сами ненулевой, есть неявное преобразование в int?, который является обнуляемыми.

В этот момент, если структура объявляет оператор == с тем же типом с обеих сторон, то это также отменено для работы с нулевыми типами.

Так что это не компилируется:

public struct Foo {} 

class Test 
{ 
    static void Main() 
    { 
     Foo x = new Foo(); 
     if (x == null) 
     { 
      ... 
     } 
    } 
} 

... но если вы даете Foo некоторые операторы, это делает компилировать и без предупреждения:

public struct Foo 
{ 
    public static bool operator ==(Foo x, Foo y) { return true; } 
    public static bool operator !=(Foo x, Foo y) { return false; } 
    public override bool Equals(object x) { return false; } 
    public override int GetHashCode() { return 0; } 
} 

Оператор вызова не входит в скомпилированный код, потому что компилятор знает, что RHS имеет значение NULL.

Так код выше форм (где Foo может быть заменены на любом не обнуляемом struct) имеет один из трех результатов с # 5 компилятором MS C:

  • Внимание CS0472 (например, с int)
  • Ошибка CS0019 (пользовательские типы, которые не перегружают ==)
  • Clean компиляции (пользовательские типы, которые перегружают ==, в том числе и GuidDateTime)

Непонятно, почему компилятор рассматривает некоторые «известные» типы по-разному для обычных структур. EDIT: Как заметил Эрик в комментариях, это известная ошибка в компиляторе C#, который, как мы надеемся, зафиксирован в Roslyn.

+0

Bah, лучший ответ чем мой ... –

+0

Черт, это странно! Может быть, структурирование является исключением? –

+0

@ guillegr123: Я все еще пытаюсь это выработать ... –

1

Как Эд упоминает есть предупреждение, но предупреждение намекает на причину: int может быть автоматически отливают в int? и null является допустимым значением для переменной типа int?.

+1

skeet beat me by seconds. Черт побери! – Shlomo

+0

Ты сказал это назад. Вы хотели сказать, что 'int' может быть * неявно преобразован * в' int? '. –

+0

Ack. Спасибо Эрик. Исправленный. – Shlomo