协变与逆变的概念


假如两个类型X和Y具有特殊关系,X类型的每个值都能转换成Y类型。我们将I<X>向I<Y>的转换称为协变转换。反之我们将I<Y>向I<X>的转换称为逆变转换。

简单的举个例子:

List<string> str;
List<Object> obj;

我们知道在C#中所有引用类型都直接或间接地继承自Object类,所有string都可以转换成Object类,因此将str转换成obj是协变转换,反之则为逆变转换。

我们可以简单理解为:

  • 由派生类向基类方向转变是协变

  • 由基向派生类方向转变是逆变

关于in和out修饰符


下面用到的三个类:Animal类、Dog类、Cat类。

  • 协变:一个Cat[]也是Animal[]
  • 逆变:一个Animal[]也是Cat[]

    如果要避免类型错误,并且支持读写操作,那么只有第三种情况是安全的(不允许进行类型转换),Animal[]并不是总能当作Cat[],因为当一个客户读取数组并期望得到一个Cat,但Animal[]中包含的可能是个Dog。所以逆变规则是不安全的。

    反之,一个Cat[]也不能被当作一个Animal[]。因为总是可以把一个Dog放到Animal[]中。在协变数组,这就不能保证是安全的,因为背后的存储可以实际是Cat[]。因此协变规则也不是安全的.

    但是,只读数据类型是协变的(也就是说只需要数据只读,那么协变就是安全的),只写数据类型是逆变的(只需要数据只写,那么逆变就是安全的)

这时候我们的in修饰符和out修饰符就派上用场了:

  • 在C#4.0中使用out类型参数修饰符允许协变性,它会导致编译器验证该类型是否真的只作用于“输出”,即只用于方法的返回类型和只读属性的返回类型,永远不用于形参或者属性的赋值方法,如果验证通过则编译器会允许协变操作。
  • 在C#4.0中使用in类型参数修饰符允许逆变性,它只是编译器核实类型从未在属性的取值方法(get访问器)中出现,也没有作为方法的返回类型使用,如果检查无误则会允许逆变操作。

关于协变转换的额一些限制

  1. 只有泛型接口和泛型委托才可以是协变的。泛型类和结构永远不是协变的。
  2. 协变的来源和目标必须是引用类型不能是值类型,也就是说不能一个是object,另一个是int。
  3. 接口或委托必须声明为支持协变,编译器必须验证协变所针对的类型参数确实只用在“输出”的位置。

    参考:《C#6.0本质论》、wiki百科——协变与逆变、各种博客。

转载于:https://www.cnblogs.com/lizhenghao126/p/11053666.html

[C#]关于逆变与协变的基本概念和修饰符in与out的意义相关推荐

  1. java中的逆变、协变、不变概念讲解转载自http://www.cnblogs.com/en-heng/p/5041124.html,感谢编程路上的前辈们!

    En-Heng 无他,但手熟尔 博客园 首页 新随笔 联系 订阅 管理 随笔 - 32  文章 - 0  评论 - 33 Java中的逆变与协变 看下面一段代码 Number num = new In ...

  2. 协变逆变java_Java中的逆变与协变

    什么是逆变与协变 协变(Covariance) 如果B是A的子类,并且F(B)也是F(A)的子类,那么F即为协变 逆变(Contravariance) 如果B是A的子类,并且F(B)成了F(A)的父类 ...

  3. C#高级语法之泛型、泛型约束,类型安全、逆变和协变(思想原理)

    一.为什么使用泛型? 泛型其实就是一个不确定的类型,可以用在类和方法上,泛型在声明期间没有明确的定义类型,编译完成之后会生成一个占位符,只有在调用者调用时,传入指定的类型,才会用确切的类型将占位符替换 ...

  4. 【转】逆变与协变详解

    逆变(contravariant)与协变(covariant)是C#4新增的概念,许多书籍和博客都有讲解,我觉得都没有把它们讲清楚,搞明白了它们,可以更准确地去定义泛型委托和接口,这里我尝试画图详细解 ...

  5. 第五节:泛型(泛型类、接口、方法、委托、泛型约束、泛型缓存、逆变和协变)

    一. 泛型诞生的背景 在介绍背景之前,先来看一个案例,要求:分别输出实体model1.model2.model3的id和name值,这三个实体有相同的属性名字id和name. 1 public cla ...

  6. 跟着小老弟来学习Kotlin中的逆变和协变

    /   今日科技快讯   / 近日,小米创始人.董事长兼CEO雷军在抖音上开启了其直播带货的首秀.从晚上8点开播,到晚上10点,销售额就已经破亿.包括1000台售价49999元的透明电视在内的商品一推 ...

  7. 泛型委托的逆变和协变

    泛型委托:委托实际只是提供了4个方法的一个类定义.这4个方法包括:一个构造器.一个Invoke方法.一个BeginInvoke方法和一个EndInvoke方法.如果定义的一个委托类型指定了类型参数,编 ...

  8. ios开发ios9新特性关键字学习:泛型,逆变,协变,__kindof

    一:如何去学习?都去学习什么? 1:学习优秀项目的设计思想,多问几个为什么,为什么要这么设计,这么设计的好处是什么,还能不能在优化 ,如何应用到自己的项目中 2:学习优秀项目的代码风格,代码的封装设计 ...

  9. Scala 深入浅出实战经典 第81讲:Scala中List的构造是的类型约束逆变、协变、下界详解...

    ::将对象追加在list的head. 向一个已有list[子类x]的head部分放入另外一个对象a,对象a是子类y,如果a对象和原来list对象都同时继承自同一个父类,那这个list会显示为list[ ...

最新文章

  1. 两个免费转换视频的软件,实现服务器端Video2FLV
  2. Stack:删除并返回栈顶元素?
  3. Java 200+ 面试题补充③ Dubbo 模块
  4. 程序员的鄙视链,你被鄙视了吗?
  5. C#日期格式化,时间
  6. CSS中可以通过哪些属性定义,使得一个DOM元素不显示在浏览器可视范围内?
  7. Mapping Text to Knowledge Graph Entities using Multi-Sense LSTMs
  8. QString与std::string 有中文时的转换操作
  9. BulkInsert导入CSV文件
  10. linux系统usb触摸驱动,Linux ——usb触摸屏驱动 - usbtouchscreen
  11. 计算机怎么应用最小二乘法作图,最小二乘法应用
  12. 测量员软件测试版,测量员测距尺子app
  13. 计算机画图如何把二寸照片修改为一寸,win7使用自带画图工具把照片调整成2寸的方法...
  14. 进阶:主流的cpu插槽类型详解
  15. keil stm32标准库放在哪里_使用Keil MDK以及标准外设库创建STM32工程
  16. 区分event对象中的[clientX,offsetX,screenX,pageX]
  17. torch.distributed.init_process_group(‘gloo’, init_method=‘file://tmp/somefile’, rank=0, world_size=1
  18. 神奇的scala操作
  19. 《企业管理概论》在线平时作业1
  20. Java基础 - 集合框架(5) : Map集合、Collections

热门文章

  1. 事务不是与当前连接无关联就是已完成_mysql索引锁事务
  2. mysql 5.7 编译_MySQL5.7.20编译安装
  3. mysql 队列存储_GitHub - hongliangbest/QueueTask: 一个轻量级可拓展的队列任务、暂时支持mysql、redis等存储方式...
  4. 简述计算机绘图的应用领域试卷,计算机绘图试卷A(标准答案)
  5. [深度学习]大白话之卷积神经网络
  6. 如何才能快速匹配到大号?
  7. [渣译文] 使用 MVC 5 的 EF6 Code First 入门 系列:为ASP.NET MVC应用程序处理并发
  8. JavaScript学习笔记 1
  9. django新闻页面编写
  10. python有哪些好的学习资料或者博客