首页 > 其他分享 >5分钟彻底理解逆变协变,学不会来打我

5分钟彻底理解逆变协变,学不会来打我

时间:2023-08-10 23:55:23浏览次数:31  
标签:逆变 协变 分钟 类型 IWork 泛型 Out

其实这是c#的老知识点了,但是今天发现同事对这个竟然还一知半解,就和他们讲解了下,顺便也回顾了下,同事我也把我对这个的全部理解,融化成几分钟的讲解,保证大家5分钟内全部理解,看不懂来打我。
最后,都说c#断层严重,希望广大.neter振作起来,不要呆在舒适圈啦。

目录

协变、逆变 解决的问题

泛型类型转换

比如Person类是Student的父类,我们平时可以直接:

Person A = new Student();

这是所谓的隐式转换,相信百分之999.99%的人都知道。
然后随着大家写代码越来越多,就会遇到这样的场景。

//我有一个集合
//我手上有一批学生
IEnumerable<Student> students = new List<Student>();
//我要他们先做人
IEnumerable<Person> peoples = students;

第一次看到这种代码,其实哪怕你一点不知道协变,逆变,你也觉得这是一段正常不过的代码,因为每个学生都是人,都可以直接转成 这个类型,那我一批学生不就是一批人吗。是的,你这样想绝对没错,不然微软怎么会能让你这样写没问题还编译通过呢?
但是如果我自己写一个:

//定义一个工作的泛型接口
public interface IWork<T> 
{
            
}

实现类
public class Work<T> : IWork<T> 
{
            
}

//直接报错
IWork<Person> work = new Work<Student>();;

现实给了我们当头一棒,这时候,我们应该找到 IEnumerable,选中然后狠狠的F12去看一下,为什么官方的就可以。

我们发现官方在泛型前面多了一个out关键字。破案了~
现在我们在我们的代码中也加入out关键字

public interface IWork<out T> 
{
            
}

public class Work<T> : IWork<T> 
{
            
}
IWork<Person> work = new Work<Student>();

OK~代码正常运行。

原则核心

这里开始我们挑战五分钟速通,如果按照正常博客上来先讲概念,别说五分钟了,可能大家也就迷迷糊糊地看完了,所以我们直接整活。

核心依据

正如数学的发展是从1+1=2作为开始,我们也需要一些真理来支撑我们讲下去。那么我们的核心依据就是:
C#里,子类转父类可以直接转换
就这么短,就完事了?对,记住就行!!!

Out/In 输入输出?

讲到这里,我们继续忽悠,out是啥?来个翻译!不就是输出吗?in是啥,不就是输入吗?那么带入一下,Out不就是返回值吗,In不就是入参吗。(先假设,再假设)

In:那么根据核心依据,子类转父类可以直接转,入参如果是Person类型,那么你随便给我Student类型啥的,只要是Person类型的子类,这个方法总是类型安全的。
说白了,我就是需要一个人,你直接送我个学生,那当然可以了

Out:Out代表的是返回值,根据核心依据,我如果返回的是Student类型,你说不行,你给我返回Person类型,那我不是笑开花了,我连Student都能返回,你让我返回父类,那我不是直接转就过去了,总归是类型安全的。
说白了,我可以造个学生,结果你说给个人就行, 那不是so easy。

In示意图

Out示意图

证明

好了,我们说了这么多,至少证明下In/Out是代表的入参和返回值吧?直接show you code:
当Out作为返回值时的泛型没有问题,但是入参就报错了

当In作为入参时的泛型没有问题,但是返回值就报错了

好了,这还需要再解释吗?最后我们总结下,逆变和协变就是让方法有了泛型类型上的转换能力,强化了方法的多态能力。

问答

1.属性是否可以用逆变协变?
当然可以,属性不就是get/set方法吗哈哈。
2.为什么接口和委托可以用逆变协变,类不行?
拜托你找一下共同点,接口和委托的共同点,都是行为,也就是方法为核心。接口里不能有字段。这也印证了我说的逆变协变最终是为方法服务的。
之所以类不行,我大概理解是方法和实例是分开的,本身不和实例存储在一起,也不是每个实例一份,如果逆变和协变可以服务类,那么会出现同样的类型,但是每个实例内部的同一个字段的类型都不一样,这对于存储和类型安全都是问题。
3.逆变和协变有啥用?
当你...设计问题,我就有遇到,有时候用上能更加优雅或者灵活的写代码吧,看你吧,少年。

标签:逆变,协变,分钟,类型,IWork,泛型,Out
From: https://www.cnblogs.com/qwqwQAQ/p/17621932.html

相关文章

  • 让 GPT-4 给开源项目 GoPool Review 社区贡献者的 PR - 每天5分钟玩转 GPT 编程系列(5
    目录1.嘚瑟一下2.言归正传2.1GoPool的第一个PR2.2祭出GPT-42.3问问GPT-4怎么看这个PR2.4让GPT-4重构代码3.打完收工1.嘚瑟一下你还记得那个宣称自己性能全网第一的GolangWorkerPool不?对,就是能够GoPool,据说作者拿着GPT-4只花了3天就把这个项目肝出来了。......
  • 第4天- 1分钟 快速Docker安装clickhouse 数据库
    1.获取clickhouse镜像dockerpullyandex/clickhouse-serverdockerpullyandex/clickhouse-client2.查看安装的镜像dockerimages3.启动server端mkdirclickhousedockerrun-d--nameclickhouse-test-server--ulimitnofile=262144:262144--volume=/clickhouse:......
  • 腾讯云TCB云函数趣应用:巧用 puppeteer 五分钟实现一个云加社区个人成就爬虫...
    技术选型应用思路核心代码参数介绍HTTP访问注意事项参考资料最后奉上几个社区大佬的成就#技术选型之前一直想用云函数来做爬虫,无奈小程序云开发的云函数还未完全支持puppeteer,调用会报错。但是最近发现TCB的云函数支持puppeteer依赖,就决定用它了。另外一个原因就是它也......
  • 用 Python 自动创建 Markdown 表格 - 每天5分钟玩转 GPT 编程系列(4)
    目录1.他们居然问我要Prompts2.让GPT-4来写代码2.1我对DevChat说2.2DevChat回答2.3我又对DevChat说2.4DevChat的第二轮回答2.5我再次对DevChat说2.6DevChat回答2.7最后效果3.他们居然让我要写总结1.他们居然问我要Prompts早几天我用GPT-4写了一个Gol......
  • win10 系统下 安装VMware17 安装centos,启动2分钟后卡死 ,win10主机cpu 爆满
    win10系统下安装VMware17安装centos,启动2分钟后卡死,win10主机cpu爆满:请教了高手老师,用下面的方式解决了,哦耶!  被卡死的那滋味真难受啊,问题解决,心情倍儿爽~ ,另一篇搜到的参考文章:记一次解决VMWareUbuntu虚拟机卡死|熊孩子程序员(pkemb.com) ......
  • VimScript五分钟入门-中文翻译
    这篇文章主要是为了让你能够尽可能快地学习到vimscript的基础。你可以把这当做一个速查表。在读这篇文章之前,你应该可能已经有了一些编程经验。Vim的内建文档已经很出色了。你可以在vim里尝试:h<searchterm>来阅读更多信息。你可以通过在normal模式下键入gQ命令启动REPL环境来调......
  • 案例分享|从发现到处理,15分钟故障解决
    ......
  • #Powerbi 1分钟学会,设置有密码保护的powerbi报告
    目前,有一些朋友和笔者一样,公司暂时没有部署powerbi服务器,但是有时也需要使用powerbi共享一些看板。如果直接将制作好的报告直接发布在公网上,又存在一定的风险,即便可能只是公布1天。那么有没有办法,可以让咱们的报告能在短期内受到保护呢?今天,我们就花1分钟来学习一下,通过书签导航......
  • 五分钟教你使用GitHub寻找优质项目
    https://www.cnblogs.com/Can-daydayup/p/17581307.html 思维导航前言首先解决访问慢的问题GitHub热门栏目GitHub上直接搜项目GitHub搜索小技巧前言经常会有同学会问如何使用GitHub找到自己想要的项目,今天咱们就出一期快速入门教程五分钟教你使用GitHub寻找优质项......
  • 优测优分享-3分钟全面了解API Moke
    一、什么是密闭服务?Google测试团队的博客中,有一篇博文介绍的正是《HermeticServers(密闭服务)》。如下图所示,当被测试系统依赖了AnotherBackend,这种依赖即产生了“不可控”因素。怎么定义密闭服务呢?如果可以在一台没有网络的机器上启动整个服务并且服务可以按照预期的工作,那么......