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

【C#补全计划】协变逆变

一、协变逆变的概念

1. 协变:子类型关系的正向继承

        子类变父类 -> 感受是和谐的

2. 逆变:子类型关系的反向继承

        父类变子类 -> 感受是不和谐的

3. 协变和逆变是用来修饰泛型的

        (1)协变:out

        (2)逆变:in

4. 只有泛型接口和泛型委托能使用

5. 是用来在泛型中修饰泛型字母的

二、协变逆变的作用

1. 限定返回值和参数

        (1)用 out 修饰的泛型,只能作为返回值

        (2)用 in 修饰的泛型,只能作为参数

using System;namespace OutAndIn
{// 1. 限制返回值与参数// 无限制:既可以作为返回值,也可以作为参数delegate T deTest1<T>();delegate void deTest2<T>(T t);// 用out修饰的泛型只能作为返回值// delegate T deOut<out T>(T t); 编译报错:因为使用T作为参数类型delegate T deOut<out T>();// 用in修饰的泛型只能作为参数// delegate T deIn<in T>(T t); 编译报错:因为使用T作为返回值类型delegate void deIn<in T>(T t);interface IOut<out T>{// void test(T t); 编译报错:因为使用T作为参数类型T test();}interface IIn<in T>{void test(T t);// T test(); 编译报错:因为使用T作为返回值类型}
}

2. 结合里氏替换原则使用

using System;namespace OutAndIn
{// 1. 限制返回值与参数// 无限制:既可以作为返回值,也可以作为参数delegate T deTest1<T>();delegate void deTest2<T>(T t);// 用out修饰的泛型只能作为返回值// delegate T deOut<out T>(T t); 编译报错:因为使用T作为参数类型delegate T deOut<out T>();// 用in修饰的泛型只能作为参数// delegate T deIn<in T>(T t); 编译报错:因为使用T作为返回值类型delegate void deIn<in T>(T t);interface IOut<out T>{// void test(T t); 编译报错:因为使用T作为参数类型T test();}interface IIn<in T>{void test(T t);// T test(); 编译报错:因为使用T作为返回值类型}// 2. 结合里氏替换原则class Father {}class Son : Father {}class Program{static void Main(string[] args){// 虽然ts和tf是不同的委托,但是泛型的类型是具有父子关系的// 无out修饰:deTest1<Son> ts1 = () => new Son();// deTest1<Father> tf1 = ts1; 编译报错:父类型委托不可以装载子类型委托// 有out修饰:deOut<Son> os = ()  =>{Console.WriteLine("调用out修饰的Son类型委托");return new Son();};deOut<Father> of = os; // 父类型委托可以装载子类型委托// 无in修饰:deTest2<Father> tf2 = (Father f) => { };// deTest2<Son> ts2 = tf2; 编译报错:子类型委托不可以装载父类型委托// 有in修饰:deIn<Father> iF = (Father f) =>{Console.WriteLine("调用in修饰的Father类型委托");};deIn<Son> iS = iF; // 子类型委托可以装载父类型委托Father f = of(); // 实际调用的是osiS(new Son()); // 实际调用的是iF}}
}

        今天的学习就到这里了。感谢阅读。

        再见!

http://www.dtcms.com/a/336745.html

相关文章:

  • C++入门自学Day11-- String, Vector, List 复习
  • Linux 下基于 TCP 的 C 语言客户端/服务器通信详解(三个示例逐步进阶)
  • 高级堆结构
  • STM32学习笔记13-通信协议I2CMPU6050
  • Vue深入组件:Props 详解1
  • 文本邮箱提取工具
  • ARM汇编代码新手入门
  • 信号量机制中---生产者 - 消费者问题
  • LeetCode 1323: 6和9组成的最大数字
  • 计算机网络技术学习-day2《IP地址分类解析》
  • 中国星网发展情况全面分析
  • 每日Java面试系列(15):进阶篇(String不可变的原因、性能问题、String三剑客、自定义不可变设计、组合优于继承等相关问题)
  • 数据结构——线性表
  • 蓝桥杯C++
  • 下降路径最小和
  • 《Java高并发核心编程》笔记汇总
  • 【Java企业级开发】(八)Spring框架中Web项目构建
  • 【高等数学】第九章 多元函数微分法及其应用——第六节 多元函数微分学的几何应用
  • Transformer架构的数学本质:从注意力机制到大模型时代的技术内核
  • AI 编程在老项目中的困境与改进方向
  • 负载测试与压力测试详解
  • MySQL黑盒子研究工具 strace
  • 基于因果性的深层语义知识图谱对文本预处理的积极影响
  • Perf使用详解
  • AI系统性思维复盘概述
  • 【FreeRTOS】事件组
  • 电力设备状态监测与健康管理:从数据感知到智能决策的技术实践​
  • 通达信【牛股妖股埋伏】副图+选股指标
  • 报错注入原理与全方法总结
  • HAL-ADC配置