Почему мне разрешено сравнивать тип с нулевым значением с нулем?
Возможный дубликат:
С# в порядке со сравнением типов значений с нулем
Если я попытаюсь назначить null
нечетному типу в С#:
System.DateTime time = null;
Я получу ошибку времени компиляции:
error CS0037: Невозможно преобразовать значение null в 'System.DateTime', потому что это тип с нулевым значением
что имеет смысл. Но если сравнивать один и тот же тип с null
:
System.DateTime time = obtainFromSomewhere();
if( time == null ) {
//whatever;
}
нет ошибки времени компиляции. Для меня это не имеет смысла - если я не могу назначить null
, то зачем ему когда-либо быть null
?
Почему мне разрешено сравнивать тип с нулевым значением с null
?
Ответы
Ответ 1
Причина, по которой это работает для DateTime
, заключается в том, что DateTime
определяет ее собственный оператор ==
. Поскольку он делает это, он получает отмененную версию оператора, которая может использоваться с DateTime?
. Поскольку DateTime
и null
могут быть неявно преобразованы в DateTime?
, сравнение компилируется, но всегда будет оцениваться как false во время выполнения.
Спасибо Мэтту Эллен за то, что мой первоначальный ответ не охватывал пример в вопросе.
Ответ 2
Из-за Бокс.
DateTime
может быть помечен как object
и, таким образом, он становится ссылкой, которую можно сравнить с null
(хотя она всегда будет false
).
Однако объект (null
) не может быть снова распакован на DateTime
, поэтому его нельзя назначить DateTime
.
Пример:
вы могли бы сделать
object now = DateTime.Now;
bool isNull = now == null
EDIT:
Как отметил Брайан Расмуссен, я ошибался в теории бокса. Бокс будет происходить только в том случае, если он явно подвергнут объекту, как в моем примере, или в (object)DateTime.Now == null
.
Ответ 3
Существует неявное преобразование в нулевой тип с .NET 2.0 (см., что сказал Эрик Липперт здесь).
Компилятор выдает следующее предупреждение, указывающее на то, что происходит преобразование:
C:\>c:\windows\Microsoft.NET\Framework\v2.0.50727\csc test.cs
Microsoft (R) Visual C# 2005 Compiler version 8.00.50727.4927
for Microsoft (R) Windows (R) 2005 Framework version 2.0.50727
test.cs(16,12): warning CS0464: Comparing with null of type 'int?' always produces 'false'
В .NET 1.1, который не имеет типов с нулевым значением, ваш образец кода не был бы законным:
C:\>c:\windows\Microsoft.NET\Framework\v1.1.4322\csc test.cs
Microsoft (R) Visual C# .NET Compiler version 7.10.3052.4
for Microsoft (R) .NET Framework version 1.1.4322
Copyright (C) Microsoft Corporation 2001-2002. All rights reserved.
test.cs(12,13): error CS0019: Operator '==' cannot be applied to operands of type 'System.DateTime' and ''
Ответ 4
он должен быть нулевым типом:
System.DateTime? time = null;
ваш код должен выглядеть следующим образом:
System.DateTime? time = obtainFromSomewhere();
if( time.HasValue ) {
//use time.Value;
}
но помните, что ваша функция obtainFromSomewhere
должна возвращать тип DateTime?
.
Ответ 5
По-моему, это разрешено, потому что NULL не является реальным значением из-за отсутствия типа.
Хорошо, что допустим некоторый код, как показано ниже:
System.DateTime time = obtainFromSomewhere(); // allways a date
System.DateTime? otherTime = obtainFromSomewhereElse(); // null if nothing planned
if (time == otherTime)
{
// match
...
}
Что бы мы сделали без нулевого в любом случае?