C#中的协变和逆变
2022/2/6 1:13:18
本文主要是介绍C#中的协变和逆变,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
前言
这篇文章简单说说C#中的协变和逆变。
在C#编程中,由于存在类型之间的强制转换,很容易会出现所谓的类型可变性说法,存在协变、逆变、不变三种。
就比如前一篇文章介绍的泛型概念,如果创建了泛型类型的实例,编译器会接受泛型类型声明以及类型参数来创建构造类型。但是在日常使用过程中,我们可能会将派生类型分配给基类型的变量,有时候会出现错误。
这里就存在一个赋值兼容性问题。
每一个变量都有一种类型,可以将派生类对象的实例赋值给基类变量(好比之前子类声明的变量可以赋值给父类声明的变量一样)。
如下所示:
class People { public int Age = 27; } class AhuiPeople : People { }
People ahui = new People(); People people = new AhuiPeople(); Console.WriteLine("Age:"+people.Age); Console.ReadKey();
协变和逆变
我们按照同样的逻辑,在泛型委托中进行这种强类型的转换,会发现即使基类和派生类之间可以进行正常的转换,但是委托之间不能进行转换会出现异常错误提示。
具体如下代码所示:
delegate T AgeDelegate<T>(); static AhuiPeople GetAge() { return new AhuiPeople(); }
在转换过程中,委托的具体用法,但是这样子编译器提示错误。
AgeDelegate<AhuiPeople> ahui = GetAge; AgeDelegate<People> people = ahui;
错误提示
这就是上面解释的那样子,基类和派生类之间可以进行转换但是委托之间未存在关联,无法进行强制类型的转换。
那么想解决这个问题就引入了协变来解决。
如果派生类只是用于输出值,那么这种结构化的委托有效性之间的常数关系叫做协变,可通过主动告知编译器我们的期望,使用Out关键字标记委托声明中的类型参数。
delegate T AgeDelegate<out T>();
修改成这样子后,上面错误演示的代码编译器就可以正常编译通过了。
上面简单介绍了协变,那么接下来我们来看逆变是什么。
其实逆变就是在委托中既要声明委托类型,也要在委托方法中有实参。
这种在期望传入基类时允许传入派生对象的特性叫做逆变。 逆变使用关键字in来标记。
具体如下代码所示:
delegate void AgeDelegate<in T>(T p); static void GetAge(People p) { Console.WriteLine(p.Age); }
AgeDelegate<People> ahui = GetAge; AgeDelegate<AhuiPeople> people = ahui; people(new AhuiPeople()); Console.WriteLine(); Console.ReadKey();
输出结果
既然协变和逆变可以使用在委托上,那么接口上也可以使用,此时也需要使用out和in关键字。
寄语
人生短暂,我不想去追求自己看不见的,我只想抓住我能看得见的。
原创不易,给个关注。
我是阿辉,感谢您的阅读,如果对你有帮助,麻烦点赞、转发 谢谢。
这篇关于C#中的协变和逆变的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2022-03-01沐雪多租宝商城源码从.NetCore3.1升级到.Net6的步骤
- 2024-12-06使用Microsoft.Extensions.AI在.NET中生成嵌入向量
- 2024-11-18微软研究:RAG系统的四个层次提升理解与回答能力
- 2024-11-15C#中怎么从PEM格式的证书中提取公钥?-icode9专业技术文章分享
- 2024-11-14云架构设计——如何用diagrams.net绘制专业的AWS架构图?
- 2024-05-08首个适配Visual Studio平台的国产智能编程助手CodeGeeX正式上线!C#程序员必备效率神器!
- 2024-03-30C#设计模式之十六迭代器模式(Iterator Pattern)【行为型】
- 2024-03-29c# datetime tryparse
- 2024-02-21list find index c#
- 2024-01-24convert toint32 c#