为什么允许我将不可为null的类型与null进行比较

本文关键字:null 类型 比较 为什么 允许我 | 更新日期: 2023-09-27 17:50:27

可能重复:
C#可以将值类型与空进行比较

如果我试图将null分配给C#中不可为null的类型:

System.DateTime time = null;

我会得到一个编译时错误:

错误CS0037:无法将null转换为"System.DateTime",因为它是不可为null的值类型

这是有道理的。但如果将相同类型与null:进行比较

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

没有编译时错误。这对我来说没有意义——如果我不能分配null,那么为什么它会是null

为什么允许我将不可为null的类型与null进行比较?

为什么允许我将不可为null的类型与null进行比较

这适用于DateTime的原因是DateTime定义了自己的==运算符。因为它这样做,它得到了一个可以与DateTime?一起使用的运算符的提升版本。由于DateTimenull都可以隐式转换为DateTime?,因此比较编译,但在运行时总是计算为false。

感谢Matt Ellen指出我最初的回答没有涵盖问题中的例子。

这是因为拳击。

DateTime可以被装箱作为object,因此它成为可以与null进行比较的参考(尽管它将始终是false(。

但是,对象(null(不能开箱返回到DateTime,因此不能将其分配给DateTime

示例:你可以做

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

编辑:正如布莱恩·拉斯穆森指出的那样,我对拳击理论是错误的。只有像在我的例子中或在(object)DateTime.Now == null中那样显式地投射到对象时,才会发生拳击。

自.NET 2.0以来,有一种到可为null类型的隐式转换(请参阅Eric Lippert在这里所说的(。

编译器会向您发出以下警告,表示发生了转换:

C: C:''windows''Microsoft.NET''Framework''v2.0.50727''csc test.csMicrosoft(R(Visual C#2005编译器8.00.50727.4927版适用于Microsoft(R(Windows(R(2005 Framework 2.0.50727版test.cs(16,12(:警告CS0464:与类型为"int?"的null进行比较总是产生"false">

在没有可为null类型的.NET 1.1中,您的代码示例将不合法:

C: C:''windows''Microsoft.NET''Framework''v1.14322''csc test.csMicrosoft(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"answers"类型的操作数

它应该是一个可以为null的类型:

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
    ...
}

如果没有null,我们该怎么办?