当前位置: 首页 > ai >正文

协变(Covariance)与逆变(Contravariance)的入门理解

高级泛型类型系统特性,涉及接口委托中的类型转换。

协变(out

  • 放宽返回类型
  • 正确描述:允许使用比原始类型更具体(派生)的类型
    • 如何理解"更具体":子类比父类更丰富,所以“更具体”指的是子类。
  • 允许使用"更具体"的返回类型
  • 常用于返回类型的场景、泛型集合和接口中。如 `IEnumerable<T>` 就是协变的。

Eg:

###    Animal(基类)=>Mamal(子类)=>Lion(子子类)
// 协变:返回类型可以是更具体的类型
interface IAnimalProvider<out T> where T : Animal
{T GetAnimal(); // 返回类型可以更具体
}class LionProvider : IAnimalProvider<Lion>
{public Lion GetAnimal() {return new Lion();}
}class Program 
{static void Main() {// 协变:允许将更具体类型的提供者 // 赋值给更基础类型的引用IAnimalProvider<Lion> lionProvider = new LionProvider();IAnimalProvider<Animal> animalProvider = lionProvider; // 允许}
}

逆变(in

  • 放宽参数类型
  • 正确描述:允许使用比原始类型更基础(基类)的类型
    • 如何理解"更基础":基类是根基,所以“更基础”指的是基类。
  • 允许使用"更基础"的输入类型
  • 常用于方法参数的场景、委托和事件处理。如 `Action<T>` 和 `Func<T>` 中。

Eg:

###    Animal(基类)=>Mamal(子类)=>Lion(子子类)
// 逆变:参数类型可以是更基础的类型
interface IAnimalComparer<in T> where T : Animal
{int Compare(T x, T y); // 参数类型可以更基础
}class MammalComparer : IAnimalComparer<Mammal>
{public int Compare(Mammal x, Mammal y) //放宽参数类型{return 0;}
}class Program 
{static void Main() {// 逆变:允许将基础类型的比较器// 赋值给更具体类型的引用IAnimalComparer<Mammal> mammalComparer = new MammalComparer();IAnimalComparer<Lion> lionComparer = mammalComparer; // 允许}
}

总结

特征协变(out)逆变(in)
关键字outin
关注点返回类型参数类型
类型转换可以使用更具体的返回类型可以接受更基础的参数类型
使用场景工厂、提供者比较器、处理器

 Eg:

// 定义接口interface IAnimal{}class Dog : IAnimal{}class Bulldog : Dog{}#region 协变示例// 使用out关键字定义协变接口interface ICovariantProducer<out T>{T Produce();}class AnimalProducer<T> : ICovariantProducer<T> where T : IAnimal{private T _animal;public AnimalProducer(T animal){_animal = animal;}public T Produce() => _animal;}class Program{static void DemonstrateCovariance(){// 协变:可以将 ICovariantProducer<Bulldog> 赋值给 ICovariantProducer<Dog>ICovariantProducer<Bulldog> bulldogProducer = new AnimalProducer<Bulldog>(new Bulldog());ICovariantProducer<Dog> dogProducer = bulldogProducer;}}#endregion#region 逆变示例// 使用in关键字定义逆变接口interface IContravariantConsumer<in T>{void Consume(T item);}class AnimalConsumer<T> : IContravariantConsumer<T> where T : IAnimal{public void Consume(T animal){Debug.Log($"Consuming an animal: {animal}");}}class Program2{static void DemonstrateContravariance(){// 逆变:可以将 IContravariantConsumer<Dog> 赋值给 IContravariantConsumer<Bulldog>IContravariantConsumer<Dog> dogConsumer = new AnimalConsumer<Dog>();IContravariantConsumer<Bulldog> bulldogConsumer = dogConsumer;}}#endregion

http://www.xdnf.cn/news/4526.html

相关文章:

  • STC单片机--仿真调试
  • LLM词编码机制:词映射
  • Git笔记
  • 数据结构、刷leetcode返航版--二分【有序】5/7
  • HPDDM库使用指南与示例
  • 力扣刷题[特殊字符]
  • 力扣-hot100(旋转图像)
  • MCP系列(一)什么是MCP?
  • yolov8n-obb训练rknn模型
  • 解决二分类问题常用的模型以及优缺点和使用场景(二)
  • 重生之我在2024学Fine-tuning
  • 系统 Python 与 Conda 环境的灵活切换
  • 前端面经-VUE3篇(五)--内置组件
  • 【计算机架构】RISC(精简指令集计算机)架构
  • ABAP使用GET_TAX_PERCENTAGE 函数取税率
  • 手写 Vue 源码 === 完善依赖追踪与触发更新
  • FPGA 纯逻辑NVME raid0 IP核
  • 通配符 DNS 记录:应用场景与相关风险
  • SWiRL:数据合成、多步推理与工具使用
  • [吾爱出品][Windows] 产品销售管理系统2.0
  • Java UUID生成如何保证唯一性?深入解析与最佳实践
  • 【Redis】C++如何使用redis
  • java中ArrayList扩容机制的解析
  • 转换算子和行动算子的区别
  • 扩散模型(Diffusion Models)的革命性进展
  • 智算中心的搭建标准
  • Sat2Density论文详解——卫星-地面图像生成
  • @Transactional注解的使用
  • LangChain第三讲:大模型的输出如何格式化成字符串?
  • DIFY教程第五弹:科研论文翻译与SEO翻译应用