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