C# 协变与逆变

用最简单的最有内涵的方式进行概括

 

在OO哲学里面 有个依赖倒置,这是个oo的核心

就是用父类对象可以代表后面也许动态增加的子类对象从而增加了软件的,可扩展性,和相对稳定性,并且开启了一种oo式的逻辑范式

class A{}

class A1:A{}

class A2:A{}

。。。

用A a 这个对象可以表达A1,A2...等子类的实例  以便于应对一个维度上的需求变更

在C#语言发展中当引入泛型以后,出现了新需求,就是 如何让这种oo范式自然的涵盖到泛型这个新特性,因为泛型,基本上与其参数之间存在某种可预见之

关联。如果不引入协变与逆变的概念那么,很多泛型就不能使oo的上述这样的常规编程范式。

可以举个例子来说明

如果有个T= 狗类 (class Dog)

那么 有个泛型 Ixx<T> 这里是 Ixx<Dog> 

如果是逆变 则 Ixx<in T> 这告诉接口 Ixx<in T> 所有与T相关的 接口成员都只是输入向而不是输出向的,

这样可以使用 Ixx<SubT>  替换 Ixx<in T>了,注意这个替换就有点 oo依赖倒置的意思因为如上所说,它

把这种逻辑延续到了相关的泛型接口和委托上,如果一个接口有in限制或约束那么就可以有这种替换,为什么,有了in 这个限制 就可以用SubDog

来替换了呢? ,现实故事是这样的, Ixx<in Dog> 里面全是和狗相关的功能,这时你加入一只哈巴狗,小土狗,或藏獒,这些全是狗这个类别的,用来替换 Ixx<in Dog>

是不会产生歧义的,如果你用 Ixx<Mammalian> 哺乳动物这个类别去代替就会出问题,因为 老鼠,猴子都是哺乳动物,猴子会上树,狗不行,你这样替代就出问题了

如果用父级允许加入到 Ixx<in Dog>里面那么 Dog里面就不单纯了,不止有狗,可能还有鼠或猫 这与定义已经冲突了所以不行。

out呢? 如果 Ixx<out Dog> 这个限制说明这个接口中一切相关Dog参数的成员只有输出而没有输入操作,有了这样的限制前提,那么使用 Ixx<Parent_Dog> 去“替换”

就没问题了,为什么是这样呢?还是回到现实故事中来理解,Ixx<out Dog> 里面有各种狗,哈巴狗,土狗,藏獒什么的,全是狗,他们的最大公约就是其父级狗这个类

,所以使用其父级或给高阶的父级都没问题 象 哺乳动物, 动物,或生物这些 父级都可以,因为这样的替换不会产生歧义,具体的狗的各种功能可能在父级里面不全有,但是父级里面有的

其子类必有,所以这样的替换就无歧义,与之相反你不能使其子级做为输出,比如宠物狗 Ixx<Pet_Dog> 用来替代 Ixx<out Dog>

因为Ixx<out Dog>里面可能包含非 宠狗,这样的替换逻辑就发生了错误。

综上所述 结合现实故事的梳理我们不难理解 C# 的协变与逆变这两个比较冷门的概念了。你不必看网上太多说不到重点的相关文章而浪费时间了。

 

转载于:https://www.cnblogs.com/ProjectDD/p/11007340.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值