如果我尝试将null
分配给C#中的非可空类型:
System.DateTime time = null;
我会收到编译时错误:
错误CS0037:无法将null转换为'System.DateTime',因为它是一个不可为空的值类型
这是有道理的。但是如果将相同的类型与null
进行比较:
System.DateTime time = obtainFromSomewhere();
if( time == null ) {
//whatever;
}
没有编译时错误。这对我没有意义 - 如果我不能分配null
那么为什么它会null
?
为什么我可以将非可空类型与null
进行比较?
答案 0 :(得分:18)
这适用于DateTime
的原因是因为DateTime
定义了自己的==
运算符。因为它这样做,它获得了一个可以与DateTime?
一起使用的运算符的提升版本。由于DateTime
和null
都可以隐式转换为DateTime?
,因此比较会进行编译,但在运行时始终会求值为false。
感谢Matt Ellen指出我的原始答案没有涵盖问题中的例子。
答案 1 :(得分:5)
归功于Boxing。
DateTime
可以装箱为object
,因此它会成为可与null
进行比较的参考(尽管它始终为false
})。
但是,对象(null
)无法取消装箱返回DateTime
,因此无法将其分配给DateTime
。
实施例: 你可以做到
object now = DateTime.Now;
bool isNull = now == null
修改强>
正如布莱恩·拉斯穆森所指出的那样,拳击理论我错了。只有在我的示例或(object)DateTime.Now == null
中明确地投射到对象时才会出现拳击。
答案 2 :(得分:2)
自.NET 2.0以来,隐式转换为可空类型(请参阅Eric Lippert所说的here)。
编译器会给出以下警告,指示转换发生:
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 ''
答案 3 :(得分:1)
它应该是可以为空的类型:
System.DateTime? time = null;
您的代码应如下所示:
System.DateTime? time = obtainFromSomewhere();
if( time.HasValue ) {
//use time.Value;
}
但请记住,obtainFromSomewhere
函数应返回DateTime?
类型。
答案 4 :(得分:1)
在我看来,这是允许的,因为NULL不是任何类型的实际值。
允许使用下面的代码:
System.DateTime time = obtainFromSomewhere(); // allways a date
System.DateTime? otherTime = obtainFromSomewhereElse(); // null if nothing planned
if (time == otherTime)
{
// match
...
}