在 C# 中,委托的协变与逆变在底层是如何实现的?请解释其机制,包括类型系统与运行时支持。
考察说明
考察对 C# 委托类型系统中协变与逆变底层实现机制的理解。
回答思路
- 【回答框架 1】协变(covariance)允许将返回派生类型的方法赋值给返回基类型的委托,逆变(contravariance)允许将参数为基类型的方法赋值给参数为派生类型的委托。底层实现依托于委托类型的实际签名,并在元数据与运行时中进行适配。
- 【回答框架 2】在底层,委托本质上是封装方法引用的类,其类型兼容性在编译期由类型规则决定,在运行时则通过方法表(MethodTable)进行方法解析与调用。协变与逆变并不改变方法本身,而是调整委托类型与方法签名之间的可赋值性关系。
- 【回答框架 3】具体而言,当使用泛型委托(如 Func<out TResult> 与 Action<in T>)时,CLR 会在元数据中记录变体标记(variance),并在绑定(binding)阶段进行兼容性检查。这涉及到对类型参数的引用或值类型属性判断,以及基类型关系的推导。
- 【回答框架 4】需要注意的是,协变与逆变只适用于引用类型,不适用于值类型,且只适用于接口与委托类型。底层实现中,运行时并不改变方法调用规则,仅在类型兼容性层面提供支持,因此性能开销极小。
- 【关键点 1】协变使返回类型可向上兼容,逆变使参数类型可向下兼容。
- 【关键点 2】底层通过元数据中的变体标记和类型兼容性检查实现,运行时方法调用机制不变。
- 【关键点 3】仅适用于引用类型与泛型委托或接口,值类型不适用。
- 【易错点 1】误认为协变或逆变会改变方法调用的实际行为,实际上只影响类型兼容性。
- 【易错点 2】将值类型视为可协变或逆变,导致编译错误。