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

c# 协变与抗变

协变与抗变

1. 背景

一个简单的例子,

public class Sharp
{
}public class Rectange : Sharp
{
}

上面定义了两个简单的类,一个是图形类,一个是矩形类;它们之间有简单的继承关系:矩形是图形的一种。

接下来是常见的一种里氏替换写法:

Sharp sharp = new Rectange();

“子类引用可以直接转化成父类引用”,即 Rectange 类和 Sharp 类之间存在一种安全的隐式转换。

既然Rectange类和Sharp类之间存在一种安全的隐式转换,那数组Rectange[]和Sharp[]之间是否也存在这种安全的隐式转换呢?

这种将原本类型上存在的类型转换映射到他们的数组类型(或接口、委托等其它类型)上的能力,可称为“可变性(Variance)”。

在.NET中,唯一允许可变性的类型转换就是由继承关系带来的“子类引用->父类引用”转换,就是上面例子的写法。

再看下面这种写法:

Sharp[] sharps=new Rectange[3];

编译通过,这说明 Rectange[] 和 Sharp[] 之间存在安全的隐式转换。

2. 定义

2.1 协变定义

在具有可变性的条件下,与原始类型转换方向相同的可变性称作协变(covariant)。

2.2 抗变定义

在具有可变性的条件下,与原始类型转换方向相反的可变性称作抗变(contravariant),也称逆变。

可变性远远不只是针对映射到数组的能力,也有映射其它集合的能力如List.
很多人会问,说了这么多,到底这个协变或者抗变有什么实际价值?

举个例子,在.net 4.0之前可以这么写:

Sharp sharp = new Rectange();

但是却不能这么写:

IEnumerable<Sharp> sharps = new List<Rectange>();

4.0之后,可以允许按上面的写法了,因为泛型接口 IEnumerable<T> 被声明成如下:

public interface IEnumerable<out T> : IEnumerable

为什么接口参数类型前加了个 out 关键字就可以安全转换了?
因为在接口类型参数前加上修饰关键字 in 和 out 可以表示该类型参数支持抗变和协变,CLR 会自动在安全范围内进行转换。

目前 C# 支持协变和抗变的有两种类型:泛型接口泛型委托

由于它俩机制差不多,这里仅记录一下泛型接口的协变和抗变。

3. 泛型接口中的协变和抗变

定义一个泛型接口:

public interface ICovariant<T>
{
}

两个类各自继承一下该接口:

public class Sharp : ICovariant<Sharp>
{
}public class Rectange : Sharp, ICovariant<Rectange>
{
}

测试代码:

ICovariant<Sharp> isharp = new Sharp();
ICovariant<Rectange> irect = new Rectange(

http://www.mrgr.cn/news/80057.html

相关文章:

  • 创建线程、socket通信、recv非阻塞
  • 数字孪生中Unity模型如何才能做到在导入开发后差异最小化
  • 分布式事务的前世今生-纯理论
  • 分布式日志系统设计
  • 在idea中使用mysql(超详细)
  • Scala的隐式类,隐式参数和值,隐式对象
  • 蓝桥杯我来了
  • 【1211更新】腾讯混元Hunyuan3D-1文/图生3D模型云端镜像一键运行
  • 微服务篇面试题
  • 案例讲解自然语言处理(NLP)
  • 【从零开始入门unity游戏开发之——C#篇03】变量和常量
  • SpringBoot3集成MybatisPlus3和knife4j(swagger3兼容增强版)
  • C语言,有关const
  • Prime2_解法二:openssl解密凭据
  • tcpdump编译
  • uboot移植网络驱动过程,无法ping通mx6ull和ubuntu问题解决方案
  • C++小白实习日记——Pollnet,Efvi,UDP,数据类型转换(下)
  • 【Spark】Spark性能调优
  • GNSS误差源及差分定位
  • Elasticsearch Java Api Client中DSL语句的查询方法汇总
  • 防火墙端口跑不满速度处理
  • 【中工开发者】鸿蒙商城app
  • 谷粒商城—分布式高级①.md
  • 测试工程师八股文01|Linux系统操作
  • 字体子集化实践探索
  • 引用、常量引用与赋值、移动构造:深入解析