• 关于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类型即可,实际上也是相当于子类到父类的转换。

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

  • 相关阅读:
    sql 生成随机数 以及不重复随机数
    值提供器 AND 模型绑定器
    web项目在iis配置好后不能正确访问问题集锦,以及IIS常规设置
    js
    性能优化
    MVC3;0问题与知识点
    EntityFramework
    MSSQL2008 临时总结文档2014
    py--使用__slots__
    py--使用@property
  • 原文地址:https://www.cnblogs.com/mosakashaka/p/12651662.html
Copyright © 2020-2023  润新知