打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
协变 (covariance) 和逆变 (contravariance)。
userphoto

2013.11.12

关注

这个问题是由于 C# 的早期版本,如 C# 3.0,不支持基于泛型的协变和逆变 (co- and contravariance)。比如,

class A { }
class B : A { }

List<B> bs = new List<B>();
List<A> as = bs; // 编译器错误,无法转换 List<B> 到 List<A>。

但事实上,B 是 A 的子类,也就是 B 的实例一定是 A 的实例。但由于早期的 C# 版本对于泛型的实现是通过经典的开放类型到封闭类型的模式,导致每一个泛型的封闭类型 (如 List<A>) 是一个单独的运行时类型,它产生后,没有任何办法验证泛型参数的继承性,因此,List<A> 和 List<B> 是两个完全不相干的运行时类型,他们也就理所当然的不能转换了。

从 C# 4.0 开始,泛型开始支持可变性 (Variance),可变性分为协变 (covariance) 和逆变 (contravariance)。协变是指对于两个泛型封闭类型 T<A> 和 T<B>,如果 A 是 B 的父类,那么从 T<B> 到 T<A> 的转换何以被支持;反之,逆变使得 T<A> 到 T<B> 的转换被支持。

例如,.NET 4.0 中的 IEnumerable<T> 的声明就是 IEnumerable<out T>,out 表示接下来的泛型参数 T 支持协变。所以,下面的代码:

IEnumerable<A> as = new List<A>();
IEnumerable<B> bs = new List<B>();
as = bs;

是可以被编译的。因为 List<T> 实现了 IEnumerable<out T>。

注意,协变和逆变仅适用于接口、委托和某些类型 (如数组和 Lambda 表达式),泛型参数也仅支持引用类型,对于值类型,由于其不可被继承,所以不支持可变性。

希望我的解释对您有帮助。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
C# 泛型的协变和逆变
一些支离破碎的泛型反射技巧 (转 装配中的脑袋)
我也说 IEnumerable,ICollection,IList,List之间的区别
Java的Covariance设计原理和SAP ABAP的模拟实现
C# List<T>用法
c# – 带有IDictionary和IEnumerable的嵌套泛型
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服