Почему мне разрешено сравнивать ненулевой тип с нулевым?
Возможный дубликат:
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
...
}
Что бы мы делали без нуля в любом случае?