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

为什么不允许在C#中将空值赋给DateTime? 这是如何实施的? 这个function可以用来让你自己的类不可空?

例:

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

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

DateTime是一个值types( struct ),其中作为string是引用types( class等)。 这是关键的区别。 引用总是可以为null; 一个值不能(除非它使用Nullable<T> – 即DateTime? ),尽pipe它可以是zero'd( DateTime.MinValue ),它通常被解释为与null相同的东西(特别是在1.1中)。

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

HTH!

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

所有值types“对象”存在于堆栈中或作为引用types对象的一部分。 一种特殊的情况是,当你将一个值types的实例转换为一个Object或者一个接口时 – 这就是所谓的“boxing”,它只是创build一个只包含可以被提取的值的“虚拟引用types”对象(“unboxed”) 。

另一方面,参考types有一个标识。 一个“新的对象()”不等于任何其他的“新的对象()”,因为它们是GC堆上的独立实例。 一些引用types提供了Equals方法和重载操作符,以使它们performance得更像是价值的,例如。 一个string“abc”等于其他“abc”string,即使它们实际上是两个不同的对象。

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

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

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

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

对于一个值types为空的,必须有一些它可以拥有的,没有其他合法含义的值, 系统将会知道哪些值应该被认为是“无效的” 。 一些价值types可以满足第一个标准,而不需要任何额外的存储。 如果.net是从头开始devise的,但是可能有Object include a virtual IsLogicalNull property, and a non-virtual IsNull which would return if这个is null and, otherwise invoke its if which would return true is null and, otherwise invoke its IsLogicalNull property and return the result. If .net had done this, it would have avoided the need for the quirky boxing behavior and property and return the result. If .net had done this, it would have avoided the need for the quirky boxing behavior and Nullable的结构constraint of (an empty Nullable could be boxed as an empty Nullable could be boxed as an empty , and still be recognized as空)。

但是,当决定在.net 2.0中提供对可空值types的支持的时候,已经写了很多代码,假设像GuidDateTime这样的默认值不会被视为null 。 由于可空types中的大部分值都是可预测的默认值(即null ),因此具有null值的types,但是默认为其他types的值,将会增加比值更多的混淆。