网站配色设计,宿迁网站建设制作,网站建设与网站设计,学校后勤网站建设的作用一、前言刘大胖决定向他的师傅灯笼法师请教什么是协变和逆变。刘大胖#xff1a;师傅#xff0c;最近我在学习泛型接口的时候看到了协变和逆变#xff0c;翻了很多资料#xff0c;可还是不能完全弄懂。灯笼法师#xff1a;阿胖#xff0c;你不要被这些概念弄混#xff0… 一、前言刘大胖决定向他的师傅灯笼法师请教什么是协变和逆变。刘大胖师傅最近我在学习泛型接口的时候看到了协变和逆变翻了很多资料可还是不能完全弄懂。灯笼法师阿胖你不要被这些概念弄混编译器可不知道你说的什么协变逆变。这个问题首先你得弄懂什么叫类型的可变性。刘大胖可变性二、可变性灯笼法师对可变性是以一种类型安全的方式将一个对象作为另一对象来引用。虽然是可变但其实对象的引用地址是不会变的只是忽悠下编译器。刘大胖师傅说的将一个对象作为另一对象来引用这不就是继承么灯笼法师是的你可以看下面代码演示C#:刘大胖哦我理解了由于MemoryStream继承于Stream所以MemoryStream的对象可以变为Stream的对象原来我天天在接触可变性我竟然不知道。灯笼法师是的这种转变其实遵守了里氏替换原则爱徒你可还记得刘大胖当然为了面试早已烂熟于心。里氏替换原则(LSP)指的是所有引用基类的地方都可以使用其子类的对象。可是师傅这个和协变逆变有什么关系呢三、协变灯笼法师协变和逆变只是可变性的分类主要用于泛型接口和委托中。协变逆变只是类型转换的方向不同。我们先看下接口协变吧假如有Apple类继承于Fruit如下:灯笼法师然后现在写了一个打印水果名称的方法如下灯笼法师这时如果你打算打印一些苹果的名称你会怎么写刘大胖这不是很简单Apple继承自Fruit那可以直接使用PrintFruit类了。撸了下怎么报错了代码如下灯笼法师大胖你要理清楚虽然Apple继承Fruit但ListApple和ListFruit却一点关系也没有如图刘大胖那如果这样岂不是要为每一种水果都要定义一个PrintFruit方法我觉得官方不会不知道这个问题吧灯笼法师这种问题官方当然知道了所以才有了泛型接口的协变用以支持ListApple自动转为ListFruit。C#中使用out表示泛型参数的可协变性List没有out约束所以不能协变但它的基类IEnumable却实现了如图灯笼法师所以只要把PrintFruit的参数类型换成IEnumable就可以了如图刘大胖那为什么ListT不能加out以支持协变呢灯笼法师爱徒问的好List继承于IEnumable它比IEnumable更宽泛它支持读和写但协变只能可读主要用于约束输出参数。刘大胖好吧我回去再消化下。师傅你再讲一下什么是逆变吧。四、逆变灯笼法师逆变是相反的即支持ListFruit转为ListApple泛型接口上添加in约束输入参数。刘大胖有点懞师傅你还是用代码吧灯笼法师好吧假如现在我要让苹果列表或桔子列表可以按名称排序需要一个定义一个水果比较器此比较器能用于任何种类的水果列表代码如下灯笼法师现在给苹果和桔子列表按名称排序吧代码如下刘大胖师傅你别忽悠我Sort的参数可是要具体类型的比较器的你看代码灯笼法师大胖就这是逆变以使得基类的泛型对象替代子类的泛型对象主要是因为IComparerT中使用了in关键字来约束代码如下五、总结刘大胖哦我有点明白了协变就是支持泛型子类自动转泛型父类逆变就是支持泛型父类自动转泛型子类。灯笼法师也可以这么理解但这些转换只是针对编译器其引用地址并没有改变。翻外篇1协变String Object逆变Object String翻外篇2灯笼法师在刘大胖走后从背后拿出手机屏幕上显示来不及关闭的知乎APP把复杂的技术简单的写出来更多文章请关注我的公众号