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+零的装箱结构中,就像您自己实现此结构一样。