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

Почему integer == null является допустимым булевым выражением в С#?

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

4b9b3361

Ответ 1

Хотя сам 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) имеет один из трех результатов с компилятором MS С# 5:

  • Предупреждение CS0472 (например, с int)
  • Ошибка CS0019 (настраиваемые типы, которые не перегружают ==)
  • Чистая компиляция (настраиваемые типы, которые перегружают ==, включая Guid и DateTime)

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

Ответ 2

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