为什么C#中的DateTime不允许为null?

时间:2009-03-27 12:05:42

标签: c# non-nullable

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

示例:

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

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

6 个答案:

答案 0 :(得分:83)

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

答案 1 :(得分:9)

DateTime是一个结构而不是一个类。做一个'去定义'或在对象浏览器中查看它。

HTH!

答案 2 :(得分:7)

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

所有值类型“对象”都存在于堆栈上或作为引用类型对象的一部分。一个特例是当你将一个值类型实例转换为一个Object或一个接口时 - 这称为“boxing”,它只是创建一个虚拟引用类型对象,它只包含可以提取回的值(“unboxed”)

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

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

答案 3 :(得分:1)

DateTime是一个值类型,与int相同。只有引用类型(如string或MyCustomObject)可以为null。引用类型实际上将“引用”存储到堆上的对象位置。

这是article我发现更好地解释了它。这是MSDN article on it

答案 4 :(得分:1)

对于value-type为null,必须有一些它可以容纳的值没有其他合法含义,系统将以某种方式知道的应该被视为“null”。某些值类型可以满足第一个标准,而无需任何额外的存储空间。如果.net是从头开始设计的,考虑到可空值的概念,它可能有Object include a virtual IsLogicalNull property, and a non-virtual IsNull which would return为真if这个{{1 }} {IsLogicalNull {1}} {结构{1}}可为空的is null and, otherwise invoke its可为空的property and return the result. If .net had done this, it would have avoided the need for the quirky boxing behavior and可为空的constraint of null`)。

当决定在.net framework 2.0中为可空值类型提供支持时,已经编写了许多代码,假设(an empty和{{1}之类的内容的默认值}不会被视为could be boxed as an empty。由于可空类型中的大部分值都在于其可预测的默认值(即, and still be recognized as),因此具有Guid值但默认为其他类型的类型会增加混淆而不是值。< / p>

答案 5 :(得分:0)

string是一个类,而DateTime是一个结构。这就是为什么你不能把它设置为null