C# 中值类型为何不支持协变或逆变?
协变和逆变的概念允许对 IEnumerable<T>
进行协变使用,接受一个超类型(例如,将 IEnumerable<string>
赋值给 IEnumerable<object>
)。但是,这种行为不适用于值类型,例如 IEnumerable<int>
。
文档指出,此限制是由于方差仅适用于引用类型的原则。为了理解原因,让我们深入探讨装箱的概念及其对协变和逆变的影响。
值类型和装箱的作用
值类型直接存储在内存中,并且没有与其值分离的标识。当值类型赋值给引用变量时,会发生一个称为装箱的过程。在这个过程中,值类型被包装在一个对象包装器中,该包装器包含该值并引用原始值类型的内存位置。此包装器允许值类型被视为对象。
装箱和方差
为了使协变起作用,CLR 必须保证在将引用类型赋值给超类型时不会发生表示更改。这是因为使用代码不需要知道它正在操作的对象的确切类型。但是,对于值类型,没有对象包装器;值直接存储在内存中。因此,当值类型赋值给引用变量时,需要进行装箱操作。此装箱操作会更改值的表示,引入一层间接性。
标识保持和方差
标识保持是指在将对象赋值给基类型或派生类型时,能够保持对象相同标识的能力。在协变转换中,CLR 要求对象的标识得以保留。但是,对于值类型,装箱和拆箱操作可能会意外地更改对象的标识。这违反了协变转换的标识保持特性。
因此,为了确保标识保持转换并保持引用的有效性,CLR 仅将协变和逆变限制为引用类型。
以上是为什么在C#中不具有价值类型的协方差或违反?的详细内容。更多信息请关注PHP中文网其他相关文章!