泛型的逆变与协变

在C#中,协变(covariance)和逆变(contravariance)是两种类型参数变化的形式,它们主要用于泛型接口和委托中,以支持更加灵活的类型转换。

协变允许将派生类的实例赋值给基类的 引用,这在泛型接口和委托的返回类型中特别有用。通过使用out关键字来标记泛型接口或委托中的泛型参数,可以实现协变。

例如,假设有一个表示泛型集合的接口IEnumerable<out T>,其中T是一个泛型参数。由于这个接口使用了out关键字,T被认为是协变的。这意味着,如果有一个IEnumerable<Derived>的实例,您可以将其隐式转换为IEnumerable<Base>,其中DerivedBase的派生类。

IEnumerable<Derived> derivedList = new List<Derived>();  
IEnumerable<Base> baseList = derivedList; // 协变,因为IEnumerable<T>中的T是out参数

逆变则允许您将基类的实例赋值给派生类的引用,这在泛型接口和委托的参数类型中特别有用。通过使用in关键字来标记泛型接口或委托中的泛型参数,您可以实现逆变。

例如,假设有一个泛型接口IComparer<in T>,用于比较两个T类型的对象。由于这个接口使用了in关键字,T被认为是逆变的。这意味着,如果有一个IComparer<Base>的实例,可以将其隐式转换为IComparer<Derived>,其中DerivedBase的派生类。

IComparer<Base> baseComparer = new BaseComparer();  
IComparer<Derived> derivedComparer = baseComparer; // 逆变,因为IComparer<T>中的T是in参数

 两者实质上都遵循里氏替换原则

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Dart 是一种支持泛型的面向对象语言,它允许我们在定义类、函数或方法时使用参数化类型。泛型允许我们在不指定具体类型的情况下编写通用的代码,提高代码的重用性和安全性。 在 Dart 中,泛型的类型变化可分为两种:类型的协变(Covariance)和类型的逆变(Contravariance)。 类型的协变指的是可以将泛型类型的子类型赋值给父类型,这样就可以确保在使用泛型类型时不会发生类型不匹配的错误。例如,如果有一个泛型类 Animal<T>,其中 T 是一个类型参数,那么 Animal<Dog> 就是 Animal<Animal> 的子类型。这样我们可以使用 Animal<Animal> 类型的变量来持有 Animal<Dog> 的实例,而不会出现类型错误。 类型的逆变协变相反,指的是可以将泛型类型的父类型赋值给子类型。这样可以更灵活地使用泛型类型,更好地符合实际的业务需求。例如,如果有一个泛型类 Comparator<T>,其中 T 是一个类型参数,那么 Comparator<Animal> 就是 Comparator<Dog> 的父类型。这样我们可以使用 Comparator<Dog> 类型的变量来持有 Comparator<Animal> 的实例,而不会出现类型错误。 泛型的型变在 Dart 中使用通配符来表示,泛型类型的协变使用 extends 关键字,逆变使用 super 关键字。例如,在声明一个泛型类型时,我们可以使用 Animal<? extends Animal> 表示协变,使用 Comparator<? super Dog> 表示逆变。这样的声明帮助我们在使用泛型类型时确保类型的正确性。 总结来说,Dart 中的泛型支持类型的协变逆变,这样可以更灵活、更安全地使用泛型类型。泛型的型变通过使用通配符、extends 和 super 关键字来表示,使得泛型类型的赋值更加灵活,能够满足不同的业务需求。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值