40

为什么在 C# 中不允许将 null 分配给 DateTime?这是如何实施的?并且可以使用此功能使您自己的类不可为空吗?

例子:

string stringTest = null; // Okay
DateTime dateTimeTest = null; // Compile error

我知道我可以DateTime?在 C# 2.0 中使用以允许将 null 分配给 dateTimeTest,并且我可以在我的字符串上使用Jon Skeet 的 NonNullable 类来获取 stringTest 分配的运行时错误。我只是想知道为什么这两种类型的行为不同。

4

6 回答 6

88

DateTime是值类型 ( struct),其中字符串是引用类型 (class等)。这是关键的区别。引用可以始终为空;一个值不能(除非它使用Nullable<T>- ie DateTime?),尽管它可以是零(DateTime.MinValue),这通常被解释为与 null 相同的东西(特别是在 1.1 中)。

于 2009-03-27T12:07:43.260 回答
9

DateTime 是一个结构而不是一个类。执行“转到定义”或在对象浏览器中查看。

于 2009-03-27T12:08:27.703 回答
7

ValueTypes 和引用类型之间的重要区别是值类型具有这些“值语义”。DateTime、Int32 和所有其他值类型没有标识,Int32“42”本质上与任何其他具有相同值的 Int32 没有区别。

所有值类型“对象”要么存在于堆栈上,要么作为引用类型对象的一部分存在。一种特殊情况是当您将值类型实例转换为对象或接口时 - 这称为“装箱”,它只是创建一个虚拟引用类型对象,该对象仅包含可以提取回来的值(“未装箱”) .

另一方面,引用类型具有标识。“new Object()”不等于任何其他“new Object()”,因为它们是 GC 堆上的单独实例。一些引用类型提供 Equals 方法和重载运算符,以便它们的行为更像值,例如。一个字符串“abc”等于其他“abc”字符串,即使它们实际上是两个不同的对象。

因此,当您有引用时,它可以包含有效对象的地址,也可以为 null。当值类型对象全为零时,它们只是零。例如。整数零、浮点零、布尔值 false 或 DateTime.MinValue。如果您需要区分“零”和“缺失值/空值”,则需要使用单独的布尔标志,或者更好的是,使用 .NET 2.0 中的 Nullable<T> 类。这只是值加上一个布尔标志。在 CLR 中也有支持,因此使用 HasValue=false 对 Nullable 进行装箱会导致空引用,而不是在使用 false+零的装箱结构中,就像您自己实现此结构一样。

于 2009-03-27T12:31:06.480 回答
1

DateTime 是一个值类型,与 int 相同。只有引用类型(如字符串或 MyCustomObject)可以为空。引用类型确实存储了对堆上对象位置的“引用”。

这是我发现的一篇文章,可以更好地解释它。这是关于它的 MSDN 文章

于 2009-03-27T12:09:00.263 回答
1

对于一个值为 null 的值类型,它必须有一些值它可以持有,它没有其他合法含义,并且系统会以某种方式知道应该被视为 "null"。一些值类型可以满足第一个标准,而不需要任何额外的存储空间。如果 .net 的设计从一开始就考虑到了可空值的概念,它可能有Object include a virtualIsLogicalNull property, and a non-virtualIsNull tr ​​ue this which would returnIsLogicalNull struct Nullable Nullable Nullable null`)。ifis null and, otherwise invoke itsproperty and return the result. If .net had done this, it would have avoided the need for the quirky boxing behavior andconstraint of(an emptycould be boxed as an empty, and still be recognized as

然而,当决定在 .net 框架 2.0 中提供对可空值类型的支持时,已经编写了很多代码,它们假定像GuidDateTime不会被视为null. 由于可空类型中的大部分值与其可预测的默认值(即null)有关,因此具有具有null值但默认为其他值的类型会比值增加更多的混乱。

于 2012-05-30T15:19:04.007 回答
0

string 是一个类,而 DateTime 是一个结构。这就是为什么您不能将其设置为 null

于 2009-03-27T12:10:09.463 回答