为什么 C# 中 DateTime 不允许为 null?
为什么 C# 中不允许将 DateTime 赋给 null? 这是如何实施的? 这个功能可以用来使您自己的类不可为空吗?
示例:
string stringTest = null; // Okay
DateTime dateTimeTest = null; // Compile error
我知道我可以在 C# 2.0 中使用 DateTime?
来允许将 null 分配给 dateTimeTest 并且我可以使用 Jon Skeet 的 NonNullable 类 在我的字符串上,以获取 stringTest 分配的运行时错误。 我只是想知道为什么这两种类型的行为不同。
Why it is not allowed to assign null to a DateTime in C#? How has this been implemented? And can this feature be used to make your own classes non-nullable?
Example:
string stringTest = null; // Okay
DateTime dateTimeTest = null; // Compile error
I know that I can use DateTime?
in C# 2.0 to allow null to be assigned to dateTimeTest and that I could use Jon Skeet's NonNullable class on my string to get a run time error on the assignment of stringTest. I'm just wondering why the two types behave differently.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
DateTime
是值类型(struct
),其中 string 是引用类型(class
等)。 这是关键的区别。 引用始终可以为空; 值不能(除非它使用Nullable
- 即DateTime?
),尽管它可以为零 (DateTime.MinValue),通常被解释为与 null 相同的东西(尤其是在 1.1 中)。
DateTime
is a value-type (struct
), where-as string is a reference-type (class
etc). That is the key difference. A reference can always be null; a value can't (unless it usesNullable<T>
- i.e.DateTime?
), although it can be zero'd (DateTime.MinValue
), which is often interpreted as the same thing as null (esp. in 1.1).DateTime 是一个结构体而不是一个类。 执行“转到定义”或在对象浏览器中查看它以查看。
哈!
DateTime is a struct and not a class. Do a 'go to definition' or look at it in the object browser to see.
HTH!
ValueType 和引用类型之间的重要区别在于值类型具有这些“值语义”。 DateTime、Int32 和所有其他值类型没有标识,Int32“42”本质上与具有相同值的任何其他 Int32 没有区别。
所有值类型“对象”都存在于堆栈中或作为引用类型对象的一部分。 一种特殊情况是当您将值类型实例转换为对象或接口时 - 这称为“装箱”,它只是创建一个虚拟引用类型对象,该对象仅包含可以提取回来的值(“拆箱”) 。
另一方面,引用类型具有标识。 “new Object()”不等于任何其他“new Object()”,因为它们是 GC 堆上的单独实例。 一些引用类型提供 Equals 方法和重载运算符,以便它们的行为更像值,例如。 字符串“abc”等于其他“abc”字符串,即使它们实际上是两个不同的对象。
因此,当您有一个引用时,它可以包含有效对象的地址,也可以为空。 当值类型对象全为零时,它们只是零。 例如。 整数零、浮点零、布尔值 false 或 DateTime.MinValue。 如果需要区分“零”和“值缺失/空”,则需要使用单独的布尔标志,或者更好的是,使用 Nullable。 .NET 2.0 中的类。 这只是该值加上一个布尔标志。 CLR 中还支持使用 HasValue=false 对 Nullable 进行装箱会导致空引用,而不是使用 false+0 装箱结构,就像您自己实现此结构一样。
The important distinction between ValueTypes and reference types is that value types have these "value semantics". A DateTime, Int32 and all other value types have no identity, an Int32 "42" is essentially indistinguishable from any other Int32 with the same value.
All value type "objects" exist either on stack or as a part of a reference type object. One special case is when you cast a value type instance to an Object or an interface - this is called "boxing", and it simply creates a dummy reference-type object which only contains the value that can be extracted back ("unboxed").
Reference types, on the other hand, have an identity. a "new Object()" does not equal any other "new Object()", because they are separate instances on the GC heap. Some reference types provide Equals method and overloaded operators so that they behave more value-like, eg. a String "abc" equals other "abc" String even if they are in fact two different objects.
So when you have a reference, it can either contain the address of a valid object, or it can be null. When value type objects are all-zero, they are simply zero. Eg. an integer zero, a float zero, Boolean false, or DateTime.MinValue. If you need to distinguish between "zero" and "value missing/null", you need to use either a separate Boolean flag, or, better yet, use the Nullable<T> class in .NET 2.0. Which is simply the value plus a Boolean flag. There's also support in the CLR so that boxing of a Nullable with HasValue=false results in a null reference, not in a boxed structure with false+zero, as it would if you were to implement this structure yourself.
DateTime 是一个值类型,与 int 相同。 只有引用类型(如字符串或 MyCustomObject)可以为 null。 引用类型实际上存储对堆上对象位置的“引用”。
这是一篇文章我发现它解释得更好。 这是有关它的 MSDN 文章
DateTime is a value type, same as an int. Only reference types (like string or MyCustomObject) can be null. Reference types really store "references" to the objects location on the heap.
here's a article I found that explains it better. and here's the MSDN article on it
对于一个值为 null 的值类型,必须有某个它可以保存的值,该值没有其他合法含义,并且系统会以某种方式知道该值应该被视为“null”。 某些值类型可以满足第一个标准,而不需要任何额外的存储。 如果 .net 在设计之初就考虑到了可为 null 值的概念,那么它可能会让
Object 包含一个虚拟
IsLogicalNull属性和一个非虚拟
IsNull如果
this为 null,则返回
true,否则调用其
IsLogicalNull属性并返回结果。 如果 .net 这样做了,它就可以避免奇怪的装箱行为和 struct
Nullable
约束(一个空的
Nullable可以是装箱为空
Nullable,并且仍然被识别为
null`)。然而,当决定在 .net Framework 2.0 中提供对可为空值类型的支持时,已经编写了许多代码,这些代码假定
Guid
和DateTime 等内容的默认值
不会被视为null
。 由于可空类型中的大部分值取决于其可预测的默认值(即null
),因此具有null
值但默认为其他值的类型会添加更多的是混乱而不是价值。For a value-type to be null, there must be some value it can hold which would have no other legitimate meaning, and which the system will somehow know should be regarded as "null". Some value types could meet the first criterion without requiring any extra storage. If .net had been designed from the ground up with the concept of nullable values in mind, it could have had
Object include a virtual
IsLogicalNullproperty, and a non-virtual
IsNullwhich would return
trueif
thisis null and, otherwise invoke its
IsLogicalNullproperty and return the result. If .net had done this, it would have avoided the need for the quirky boxing behavior and
structconstraint of
Nullable(an empty
Nullablecould be boxed as an empty
Nullable, and still be recognized as
null`).By the time it was decided to provide support for nullable value types in .net framework 2.0, however, a lot of code had been written which assumed that the default values for things like
Guid
andDateTime
would not be regarded asnull
. Since much of the value in nullable types lies with their predictable default value (i.e.null
) , having types which had anull
value, but defaulted to something else, would have added more confusion than value.string 是一个类,而 DateTime 是一个结构。 这就是为什么你不能将其设置为 null
string is a class whereas DateTime is a structure. Thats why you cannot set it to null