协变,可以理解成:父类 -> 子类。父类的对象用子类替换,也可以理解成子类当父类用。
抗变,可以理解成:子类 -> 父类。子类的对象用父类替换,也可以理解成父类当子类用。抗变也常常翻译为逆变。
在c#的语言中,很多地方的调用已经隐藏了协变和抗变的使用。函数的返回类型默认是抗变的。例如,函数Func的返回类型为string,我们可以将返回的值赋给object对象。
函数的参数类型则默认是协变的。例如,函数Act的输入参数为object类型,实际操作中我们可以将string类型的对象传给函数。
在泛型接口的定义中,如果泛型类型T用out关键词标注,这个泛型接口就是协变的。而且在接口的代码里面,T只能用作返回类型,不能用作参数类型。
如果泛型类型T用in关键词标注的话,这个接口就是抗变的。在接口的代码里面,T只能用作函数的参数类型,而不能用作返回类型。
1、什么是协变、逆变?
假设:TSub是TParent的子类。
协变:如果一个泛型接口IFoo,IFoo可以转换为IFoo的话,我们称这个过程为协变,IFoo支持对参数T的协变。
逆变:如果一个泛型接口IFoo,IFoo可以转换为IFoo的话,我们称这个过程为逆变,IFoo支持对参数T的逆变。
2、为什么要有协变、逆变?
通常只有具备继承关系的对象才可以发生隐式类型转换,如Base b=new sub()。
协变和逆变可以使得更多的类型之间能够实现隐式类型转换、类型安全性有了保障。
3、为什么泛型接口要引入协变、逆变?
基于以上原因的同时、许多接口仅仅将类型参数用于参数或返回值。所以支持协变和逆变后泛型的使用上有了更大的灵活性
4. 为什么协变和逆变对泛型有很多限制?
否则的话,这样的类型转换不安全。
网友评论