(八)CSharp-泛型协变和逆变(3)

news/2024/2/28 17:06:45

一、协变和逆变

可变性分为三种: 协变、逆变和不变。

协变和逆变:泛型接口泛型委托添加了一个处理类型转换问题的扩展。

问题: 当两个类对象是继承与派生的关系时,由于编译器通过泛型实例化时没法确认它们之间的关系,导致派生类对象不能赋值给基类对象。反之亦然,基类对象不能赋值给派生类对象。

解决: 当泛型接口或泛型委托实例化两个对象时(基类对象和派生类对象),通过协变和逆变的方式,来解决一个对象不能赋值给另一个对象的问题。

二、协变

非泛型类的代码例子:

class Animal
{public int NumberOfLegs = 4;}class Dog:Animal{}class Program
{
static void Main()
{
Animal a1 = new Animal();
Animal a2 = new Dog();
}}

赋值兼容性

每一个变量都有一种类型,你可以将派生类型的对象赋值给基类型的变量,这叫作赋值兼容性。

请添加图片描述

但是对于泛型委托就不一样了,赋值原则虽成立,但是编译器会报错,因为派生类型委托没有从基类型委托派生。两者没有继承关系。

泛型委托错误的代码例子:

    class Animal { public int Legs = 4; }class Dog : Animal { }delegate T Factory<T>();class Program{static Dog MakeDog(){return new Dog();}static void Main(string[] args){Factory<Dog> dogMaker = MakeDog;//创建委托对象Factory<Animal> animalMaker = dogMaker;//赋值不兼容,错误Console.WriteLine(animalMaker().Legs.ToString());Console.ReadKey();}}

两个委托对象是同级的,它们都是从 delegate 类型派生,后者又派生自 Object 类型。两者之间没有派生关系,因此赋值兼容性不适用。

在泛型委托实例化之前,编译器并不知道 T 类型中的Dog 类和 Animal 类是继承关系。

解决赋值原则不适用问题:对于所有这样的情况(上面错误例子的情况),我们可以使用由派生类创建的委托类型,这样应该能够正常工作,因为调用代码总是期望到一个基类的引用。

协变: 仅将派生类型用作输出值与构造委托有效性之间的常数关系叫作协变。

通过增加 out 关键字改变委托声明:

//把 delegate T Factory<T>();改为:
delegate T Factory<out T>();
//编译通过

增加了 out T 类型之后,类型变量 T 是 Animal 类。T 此时是知道的,所以知道 Dog 派生自 Animal。

Factory<out T>():T 类型变量为 Animal 类

三、逆变

逆变: 传入基类时允许传入派生对象的特性叫作逆变。

 class Animal { public int Legs = 4; }class Dog : Animal { }class Program{//in:逆变关键字delegate void Action1<in T>(T a);static void ActionAnimal(Animal a){Console.WriteLine(a.Legs);}static void Main(string[] args){Action1<Animal> act1 = ActionAnimal;Action1<Dog> dog1 = act1;dog1(new Dog());Console.ReadKey();}}
Action1<in T>(T a):T 类型变量是 Dog 类

四、协变和逆变的不同

请添加图片描述

五、接口的协变和逆变

协变和逆变可以应用到委托上,也可以适用于接口。

    class Animal { public string Name; }class Dog : Animal { }interface IMyIfc<out T>{T GetFirst();}class SimpleReturn<T>:IMyIfc<T>{public T[] items = new T[2];public T GetFirst(){return items[0];}}class Program{static void DoSomething(IMyIfc<Animal> returner){Console.WriteLine(returner.GetFirst().Name);}static void Main(string[] args){SimpleReturn<Dog> dogReturner = new SimpleReturn<Dog>();dogReturner.items[0] = new Dog() { Name = "Avonlea" };IMyIfc<Animal> animalReturner = dogReturner;DoSomething(animalReturner);Console.ReadKey();}}

六、关于可变性的更多内容

除了显式的协变和逆变,编译器还可以自动识别某个已构建的委托是协变还是逆变并且进行类型强制转换。(发生在没有为对象的类型赋值的时候)

    class Animal { public int Legs = 4; }class Dog : Animal { }class Program{delegate T Factory<out T>();static Dog MakeDog() { return new Dog(); }static void Main(string[] args){Factory<Animal> animalMaker1 = MakeDog;Factory<Dog> dogMaker = MakeDog;//隐式强制转换,不需要 out 也可以Factory<Animal> animalMaker2 = dogMaker; // 需要 out 标识符Factory<Animal> animalMaker3 = new Factory<Dog>(MakeDog);// 需要 out 标识符Console.ReadKey();}}

可变性的重要点:

  • 可变性处理的是可以使用基类型替换派生类型(或者派生类转换为基类)的安全情况。
  • 使用 in 和 out 关键字的显式变化只适用于委托和接口。
  • 不包括 in 和 out 关键字的委托和接口类型参数是不变的。
delegate T Factory<out R, in S, T>();
//out R:协变
//in S:逆变
//T:不变

http://www.ppmy.cn/news/327890.html

相关文章

Mac电脑删除第三方软件工具CleanMyMac X

经常使用Mac的人都知道&#xff0c;Mac除了可以在AppStore下载应用程序&#xff0c;还有许多软件是需要在网页上搜索下载的第三方软件。那么这类第三方软件软件除了下载方式不同之外还有什么是和从App store下载的软件有区别的吗&#xff1f;答案是肯定的&#xff0c;那就是这些…

CSS基础学习--4 创建式样

一、插入样式表的几种方法&#xff1f; 外部样式表内部样式表内联样式 二、外部样式表 使用前提&#xff1a;当样式需要应用于很多页面时&#xff0c;外部样式表将是理想的选择。 在使用外部样式表的情况下&#xff0c;你可以通过改变一个文件来改变整个站点的外观。每个页…

怎样防止苹果系统更新_苹果xs换过原装屏幕可以更新14系统吗?

展开全部 苹果2113xs换过原装屏幕是可以更新14系统的。 iPhone 11系列&#xff0c;5261iPhone XS、iPhone XS Max、iPhone XR、iPhone X、iPhone 8、iPhone 8 Plus等都是可以更4102新14系统的。IOS14还赋予了用户1653更多的权限&#xff0c;这是iOS系统的一次大胆尝试。 虽然苹…

苹果怎么换个性化主题

现在的手机上都有个性化设置&#xff0c;可以把手机设置成自己喜欢的样子&#xff0c;比如说壁纸&#xff0c;封面等等&#xff0c;苹果手机更换主题的方式是和别的手机不一样的&#xff0c;那么苹果怎么更换个性化主题呢&#xff1f; 1.注册apple id。注册apple id&#xff0…

导致Android手机崩溃的壁纸,使用错误的壁纸会使你的Android手机崩溃

原标题&#xff1a;使用错误的壁纸会使你的Android手机崩溃 现代智能手机是非常复杂的&#xff0c;能够显示大量的内容&#xff0c;并能浏览一系列复杂的色域、文件格式和媒体类型。然而&#xff0c;其中一些功能会以意想不到的方式影响到正常使用。 Twitter用户Ice Universe发…

苹果手机以旧换新价格表_苹果支持安卓手机以旧换新;索尼公司将更名;百度网盘推出“防误删”文件恢复服务...

(图源水印&#xff0c;内容整合&#xff0c;侵删) 早上好&#xff0c;今天是2020年5月21日&#xff0c;为各位朋友带来近日的数码科技快讯。 索尼公司将在明年更名为索尼集团公司 (PingWest品玩消息)5月19日讯&#xff0c;索尼公司今天宣布&#xff0c;从下一财年开始&#xff…

一加android8稳定版,一加3更新最新资讯

上个月&#xff0c;一加宣布了其手机软件维护计划&#xff0c;同谷歌一样&#xff0c;一加承诺为手机提供2年的Android系统大版本更新&#xff0c;然后再来一年的安全维护性更新。 一加 3 是一加在 2016 年 6 月份发布的一款旗舰手机&#xff0c;因为可以刷很多第三方ROM&#…

APP适配IOS8,iPhone6和Plus截图简要说明,有iP6截图下载供研究(原创)

有幸在9月25日拿到了iP6和iP6 Plus的真机&#xff0c;恰好又要做适配APP的工作&#xff08;从iphone5上适配到iphone6和ip6 plus上&#xff09;&#xff0c;所以在真机上研究了下苹果官方在不同分辨率下对系统APP所做的适配。同时在网上也没找到相关的真机对比截图说明什么的&a…

新版 iPhone 名称:iPhone X、iPhone 8 和 iPhone 8 Plus

通过已泄漏的 iOS 11 GM 固件文件代码&#xff0c;基本敲定了今年 iPhone 三款新机的名称&#xff0c;并非为过去一直所流传的 iPhone 7s、iPhone 7s Plus 和 iPhone 8&#xff0c;而是跳过了 7S 的命名&#xff0c;直接采用 iPhone X、iPhone 8 和 iPhone 8 Plus&#xff0c;并…

android 5.0 ios 8,系统:Android 5.0与iOS 8谁更便捷?

系统&#xff1a;Android 5.0与iOS 8谁更便捷&#xff1f; 系统&#xff1a;Android 5.0与iOS 8谁更便捷&#xff1f; 在系统及UI方面可以说是两款机型所存在最根本的差别&#xff0c;Android与iOS的发展思路也并不相同&#xff0c;Android则更加开放&#xff0c;对于应用程序及…

(数组) 1991. 找到数组的中间位置 ——【Leetcode每日一题】

❓1991. 找到数组的中间位置 难度&#xff1a;简单 给你一个下标从 0 开始的整数数组 nums &#xff0c;请你找到 最左边 的中间位置 middleIndex &#xff08;也就是所有可能中间位置下标最小的一个&#xff09;。 中间位置 middleIndex 是满足 nums[0] nums[1] ... num…

iPhone出现白苹果怎么修复?三分钟教你如何修复手机白苹果

白苹果怎么修复&#xff1f;白苹果”指的是iPhone死机变砖的一种现象。这种现象现在并不少见&#xff0c;很多小伙伴在遇到白苹果的情况时并不知道如何处理。盲目的选择错误的方法&#xff0c;导致重要的手机数据丢失。今天小编就给大家打来一个白苹果的修复教程&#xff0c;如…

苹果手机计算机怎样拉到桌面,20个你应该知道的iPhone 7实用小技巧

本文由那年那个饭桶整理,未经作者授权,请勿转载,感谢您的尊重。 听说iOS11马上就要发布,再过几个月新版iPhone8也即将上线,你真的会用你的iPhone7了吗?下面我们来介绍几个iPhone7的实用小技巧。 1.输入消息时的光标移动: 有很多新用户在疑惑输入框那么小,想要修改已经键…

苹果刷机未知错误75_被抢先体验的苹果iOS14 系统坑惨的用户,到底遇到了多少bug ,怎么降级系统...

Apple WWDC 2020终于结束了,本次大会最大的亮点毋容置疑是iOS 14。作为苹果生态链里面重要的角色,iOS每次更新大版本手机界都像春晚一样热闹非凡。这次iOS 14除了带来操作界面上的大改变,还优化了生态链产品的使用体验,从宣传看来确实有点酷。iOS 14支持的机型还是比较多的…

苹果有的功能android没有的,苹果iOS用户没有的安卓九大功能

iOS与Android之争应该还会延续很长一段时间&#xff0c;它们一起统治着96%的智能手机市场份额。选个智能手机吧&#xff0c;是Android还是iOS&#xff1f;你是希望在苹果的后花园里流连忘返呢&#xff0c;还是希望在谷歌多变的天气中享受自由呢&#xff1f;无论哪个系统都有自己…

苹果7plus专用计算机,iphone7plus怎么用 iphone7plus使用技巧【详解】

iphone7plus逐渐成为了主流手机设备,许多朋友毫不犹豫的购买了iPhone 7 Plus,但是依然有许多朋友不知道iPhone 7 Plus的使用方式,小编为大家带来了详细的iPhone 7/7 Plus使用技巧以及最专业的使用手册。 手机推荐使用手册 每台手机设备都自带了一个提示,点击提示即可进入 可以根…

【js】js前端技巧之图片格式转换(File、Blob、base64):

文章目录 一、类型简介二、BLOB 与 File&#xff1a;【1】BLOB 转 File【2】File 转 BLOB 三、 BLOB 与 base64&#xff1a;【1】BLOB(url) 转 base64【2】base64 转 BLOB 四、File 与 base64&#xff1a;【1】File 转 base64【2】base64 转 File 五、案例&#xff1a; 一、类型…

Netty实战(十二)

预置的ChannelHandler和编解码器&#xff08;二&#xff09;HTTPS、WebSocket的添加使用和大型数据写入以及几种常见的序列化 一、基于Netty的HTTPS程序1.2 使用HTTPS2.3 WebSocket 二、空闲连接和超时三、 解码基于分隔符的协议和基于长度的协议3.1 基于分割符的协议3.2 基于长…

pytorch笔记:conv2d

来自B站视频&#xff0c;API查阅&#xff0c;TORCH.NN nn.conv2d 中一般 kernel_size 是小奇数&#xff0c;padding 设置为 k − 1 2 \frac{k-1}{2} 2k−1​&#xff08;实际上padding的是 k − 1 k-1 k−1&#xff0c;因为参数的意义是左右各padding&#xff09;&#xff0c;

【漏洞复现】Apache RocketMQ 命令注入漏洞(CVE-2023-33246)

文章目录 前言声明一、漏洞描述二、漏洞危害三、影响版本四、环境搭建五、漏洞复现六、修复建议 前言 RocketMQ 是阿里巴巴在2012年开发的分布式消息中间件&#xff0c;专为万亿级超大规模的消息处理而设计&#xff0c;具有高吞吐量、低延迟、海量堆积、顺序收发等特点。同时它…
最新文章