.NET 中的值类型很奇怪,尽管它们是派生自名为ValueType
. 对于每个值类型,都有一个堆对象类型,它的行为类似于派生自 的类对象ValueType
,但值类型存储位置包含一个字节集合,这些字节要么表示原始值,要么是保存所有字节所需的字节的串联它的公共和私人领域。
由于值类型存储位置只保存表示其值所需的字节,并且既不保存类型信息,也不保存对将保存类型信息的对象的任何引用,因此使用值类型存储位置的代码必须确切地知道它是什么。
传统的继承要求对象保存有关其自身类型的信息,但没有规定值类型可以通过哪些方式来做到这一点。
对于 .NET 来说,通过一些特殊规则允许某些有限形式的值类型继承在概念上是可能的(并且有用的),例如BaseStructure
变量只能保存 aBaseStructure
而不能保存DerivedStructure
. 可以定义一个StructureUser<T> where T:BaseStructure
,并且这样的类或方法可以接受BaseStructure
和使用这些成员的任何派生类——包括字段——这些成员对于基类是通用的。
不幸的是,很难为泛型定义规则,使其在允许的场景中表现一致,而又不破坏任何现有代码。
例如,在一个类Foo<T,U> where T:U
中,总是可以将 a 存储T
到一个 type 的变量中U
,即使它U
是一个值类型(即因为值类型是密封的,T
并且U
保证是相同的类型)。如果U
可以是可继承的值类型并且T
可以是派生的,则这样的保证将不成立。
考虑到与这种继承相关的困难,一个更有用的替代方法是提供一种安全(即使是有限的)方法,通过该方法属性可以暴露一个 byref 或一个 const-byref(一个 byref 是在参数使用时传递的东西限定符ref
)。
这样的特性将消除字段和属性之间不可避免的语义区别,并且取决于它是如何实现的,即使在与类一起使用时也可以提供一些主要优势(例如,它可以允许有效混合不可变和可变类型)。