zoukankan      html  css  js  c++  java
  • 关于c#中逆变和协变的理解

    逆变和协变的解释

    逆变和协变都是针对模板类/接口中的参数类型来说的。
    假定一个父类Father, 一个子类Child, 一个模板类SampleTemplate<T>

    简单来说

    • 协变(covariant): 需要SampleTemplate<Father>的地方,可以传入SampleTemplate<Child>。常见的协变类型:IEnumberable
    • 逆变:需要SampleTemplate<Child>的地方,可以传入SampleTemplate<Father>。常见的逆变类型:List<Child>.Sort函数使用的IComparer

    理解

    面向对象编程中,很容易理解,需要父类的地方,都可以使用子类。
    反之需要子类的地方,却不能使用父类。

    所以协变看起来似乎理所当然,而逆变看起来有点反逻辑。

    这里首先看一下,如何定义一个模板类是否支持逆变或者协变。

    • 协变: SampleTemplate<out T>
    • 逆变: SampleTemplate<in T>

    这里的inout是什么意思?

    结合前面的IEnumerable<out T>IComparer<in T>

    • 协变:在IEnumberable中,如果一个函数需要IEnumberable<Father>作为入参,我们传IEnumerbale<Child>也可以,因为我们使用这个IEnumerable时,是从其中获取元素,作为Father处理,所以IEnumerable中的数据是向的,对应out。所以传入Child类,输出Father类没有问题。
    • 逆变:当List<Child>类的Sort调用IComparer时,Sort函数签名要求的IComparer<Child>,实际表明它会向IComparer传入一个Child类型,而这个类型会在IComparer内部使用,于是对应in入方向。自然只要实际实现的模板类,能接受Child类型即可,实际上也是相当于子类到父类的转换。

    所以逆变和协变,对应的都是子类向父类的转换(子类也不可能向父类转换),不同点在于协变是模板类可以接收子类参数而输出父类;而逆变是模板类本身是作为被输入的实体,由外部输入子类,模板类把他当作父类使用。

  • 相关阅读:
    Linux基本知识
    Linux 基金会发起开源创新计划,为全球对抗 COVID-19 提供基础架构
    单片机程序设计有十层功力,你现在在哪一层?
    C语言太复杂?CUDA Python也能实现并行计算加速!
    Java 基础 子类赋值给父类问题
    SpringBlade AVUE 拖拽排序
    java 基础 Long类型 判断是否相等
    数字量输入模块和模拟量输入模块的区别是什么?
    模拟量输入模块和模拟量输出模块的应用范围
    NB-IOT关键技术分析
  • 原文地址:https://www.cnblogs.com/mosakashaka/p/12651662.html
Copyright © 2011-2022 走看看