Почему мне разрешено сравнивать ненулевой тип с нулевым?

Возможный дубликат:
C# хорошо со сравнением типов значений к нулю

Если я попытаюсь назначить null к необнуляемому типу в C#:

System.DateTime time = null;

Я получу ошибку во время компиляции:

ошибка CS0037: невозможно преобразовать значение NULL в "System.DateTime", так как это тип значения, не допускающий значения NULL

что имеет смысл. Но если сравнить тот же тип с null:

System.DateTime time = obtainFromSomewhere();
if( time == null ) {
    //whatever;
}

нет ошибки времени компиляции. Это не имеет смысла для меня - если я не могу назначить null тогда с чего бы это null?

Почему мне разрешено сравнивать ненулевой тип с null?

5 ответов

Решение

Причина, по которой это работает DateTime, это потому что DateTime определяет это самостоятельно == оператор. Поскольку он делает это, он получает отмененную версию оператора, которая может использоваться с DateTime?, Поскольку оба DateTime а также null может быть неявно преобразовано в DateTime?, сравнение компилируется, но всегда будет иметь значение false во время выполнения.

Спасибо Мэтту Эллену за то, что он указал на тот факт, что мой первоначальный ответ не охватывал пример в вопросе.

Это из-за бокса.

DateTime может быть упакован как object и, таким образом, он становится эталоном, который можно сравнить с null (хотя это всегда будет false).

Тем не менее, объект (null) не может быть распакован обратно DateTimeтаким образом, он не может быть назначен DateTime,

Пример: вы могли бы сделать

object now = DateTime.Now;
bool isNull = now == null

РЕДАКТИРОВАТЬ: Как отметил Брайан Расмуссен, я был не прав с теорией бокса. Бокс будет происходить, только если явно приведен к объекту, как в моем примере или в (object)DateTime.Now == null,

Начиная с.NET 2.0 существует неявное преобразование в тип NULL. (Посмотрите, что сказал Эрик Липперт здесь).

Компилятор выдает следующее предупреждение о том, что преобразование имеет место:

C: \> c: \ windows \ Microsoft.NET \ Framework \ v2.0.50727 \ csc test.cs
Microsoft (R) Visual C# 2005, версия компилятора 8.00.50727.4927
для Microsoft (R) Windows (R) 2005 Framework версия 2.0.50727

test.cs (16,12): предупреждение CS0464: сравнение с нулем типа int? всегда выдает "ложь"

В.NET 1.1, в которой не было типов, допускающих обнуляемость, ваш пример кода был бы недопустим:

C: \> c: \ windows \ Microsoft.NET \ Framework \ v1.1.4322 \ csc test.cs Компилятор Microsoft (R) Visual C# .NET версии 7.10.3052.4 для Microsoft (R) .NET Framework версии 1.1.4322 Авторское право (C) Microsoft Corporation 2001-2002. Все права защищены.

test.cs(12,13): ошибка CS0019: оператор '==' нельзя применить к операндам типа 'System.DateTime' и '' 

Это должен быть обнуляемый тип:

System.DateTime? time = null;

ваш код должен выглядеть так:

System.DateTime? time = obtainFromSomewhere();
if( time.HasValue ) {
    //use time.Value;
}

но помни свой obtainFromSomewhere функция должна вернуть DateTime? тип.

На мой взгляд, это разрешено, потому что NULL не является реальным значением ни от какого типа.

Хорошо, разрешен код, подобный приведенному ниже:

System.DateTime time = obtainFromSomewhere(); // allways a date
System.DateTime? otherTime = obtainFromSomewhereElse(); // null if nothing planned

if (time == otherTime)
{
    // match
    ...
}

Что бы мы делали без нуля в любом случае?

Другие вопросы по тегам