一个简单例子理解C#的协变和逆变
关于协变逆变,SolidMango的解释是比较可取的。有了协变,比如,在需要返回IEnumerable<object>类型的时候,可以使用IEnmerable<string>来替代;有了逆变,比如,在需要接收IComparable<string>类型形参方法中,可以使用IComparable<object>类型实参来替代。
协变
先来体会协变。有2个具有继承关系的父类和子类。
public class Animal{public string Name { get; set; }}public class Dog : Animal{public Dog(string dogName){Name = dogName;}}
现在有一个帮助类的方法的形参类型是父类集合IEnumerable<Animal>。
public class MyHelper{public void PrintAnimalNames(IEnumerable<Animal> animals){foreach (var animal in animals){Console.WriteLine(animal.Name);}}}
有了协变,可以在PrintAnimalNames方法中传入IEnumerable<Dog>类型的实参替代IEnumerable<Animal>类型。
static void Main(string[] args){List<Dog> dogs = new List<Dog>(){new Dog("小狗petty"),new Dog("小狗lily")};//协变IEnumerable<Animal> animals = dogs;MyHelper myHelper = new MyHelper();myHelper.PrintAnimalNames(animals);Console.ReadKey();}
可见,在方法中基于基类接口类型的形参,调用该方法的时候可以传入派生类接口类型的实参。
逆变
再来体会逆变。依然是2个具有继承关系的父类和子类。
public class Animal{public string Name { get; set; }public int Age { get; set; }}public class Cat : Animal{public Cat(string catName, int catAge){Name = catName;Age = catAge;}}
现在,我们想比较基类Animal的两个实例,为此,有必要专门写一个类让他实现IComparer<Animal>接口。
public class AnimalSizeComparator : IComparer<Animal>{public int Compare(Animal x, Animal y){if (x != null && y != null){if (x.Age > y.Age){return 1;}else if (x.Age == y.Age){return 0;}else{return -1;}}else{return -1;}}}
在帮助类中的方法中,针对Cat进行比较,方法接收IComparer<Cat>类型的形参。
public class MyHelper{public void CompareCats(IComparer<Cat> catComparer){var cat1 = new Cat("小猫1",1);var cat2 = new Cat("小猫2",2);if (catComparer.Compare(cat2, cat1) > 0){Console.WriteLine("小猫2胜出");}else{Console.WriteLine("小猫1胜出");}}}
有了逆变,客户端调用MyHelper的CompareCats方法时,可以传入IComparer<Animal>类型的实参。
IComparer<Animal> animalComparer = new AnimalSizeComparator();MyHelper myHelper = new MyHelper();myHelper.CompareCats(animalComparer);Console.ReadKey();
可见,在方法中基于派生类接口类型的形参,调用该方法的时候可以传入基类接口类型的实参。
总结:在本篇的场景中,派生类接口替代父类接口,称之为协变;父类接口代替派生类接口,称之为逆变。
一个简单例子理解C#的协变和逆变的更多相关文章
- c#打包文件解压缩 C#中使用委托、接口、匿名方法、泛型委托实现加减乘除算法 一个简单例子理解C#的协变和逆变 对于过长字符串的大小比对
首先要引用一下类库:using Ionic.Zip;这个类库可以到网上下载. 下面对类库使用的封装方法: 得到指定的输入流的ZIP压缩流对象 /// <summary> /// 得到指定的 ...
- 深入理解 C# 协变和逆变
msdn 解释如下: “协变”是指能够使用与原始指定的派生类型相比,派生程度更大的类型. “逆变”则是指能够使用派生程度更小的类型. 解释的很正确,大致就是这样,不过不够直白. 直白的理解: “协变” ...
- 【转】深入理解 C# 协变和逆变
http://www.cnblogs.com/qixuejia/p/4383068.html 深入理解 C# 协变和逆变 msdn 解释如下: “协变”是指能够使用与原始指定的派生类型相比,派生程 ...
- 深入理解 C# 协变和逆变 (转载)
深入理解 C# 协变和逆变 msdn 解释如下: “协变”是指能够使用与原始指定的派生类型相比,派生程度更大的类型. “逆变”则是指能够使用派生程度更小的类型. 解释的很正确,大致就是这样,不过不 ...
- C#精粹--协变和逆变
概念 协变和逆变来源于类型和类型之间的绑定,C#4.0开始在泛型的接口和委托上支持协变和逆变,不过在这个版本之前的委托也是支持协变和逆变的.比如数组就支持协变,但是这不是一个好的特性,这C#初期版本从 ...
- Java泛型的协变与逆变
泛型擦除 Java的泛型本质上不是真正的泛型,而是利用了类型擦除(type erasure),比如下面的代码就会出现错误: 报的错误是:both methods have same erasure ...
- 一个简单例子:贫血模型or领域模型
转:一个简单例子:贫血模型or领域模型 贫血模型 我们首先用贫血模型来实现.所谓贫血模型就是模型对象之间存在完整的关联(可能存在多余的关联),但是对象除了get和set方外外几乎就没有其它的方法,整个 ...
- (转)Java中使用正则表达式的一个简单例子及常用正则分享
转自:http://www.jb51.net/article/67724.htm 这篇文章主要介绍了Java中使用正则表达式的一个简单例子及常用正则分享,本文用一个验证Email的例子讲解JAVA中如 ...
- C语言多线程的一个简单例子
多线程的一个简单例子: #include <stdio.h> #include <stdlib.h> #include <string.h> #include &l ...
随机推荐
- CMD常用命令(一)
常用命令大全 net>user heibai lovechina /add 加一个heibai的用户密码为lovechina net>localgroup Administrators h ...
- 深入了解mitmproxy(二)
主题 修改request或者response内容 介绍 mitmdump无交互界面的命令,与python脚本对接,来源于mitmproxy支持inline script,这里的script指 ...
- 微信小程序入门与实战
1. 备注:并不是真的不需要下载,只是下载的包小于1MB,给人的感觉像是不用下载 2. 3. 理论上:同一级可以有无限个,纵向只能有五级 目前小程序分包大小有以下限制: 整个小程序所有分包大小不超过 ...
- device-pixel-radio
移动web开发之像素和DPR 今天看到一个面试题,为iphone6s的自适应,答案是@media(min-device-width:414px) and(max-device-width:736px) ...
- (一)Dubbo简介
Dubbo是阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和Spring框架无缝集成.具体可以看 百度百科 https://baike.ba ...
- C++资源之不完全导引
1,前言 无数次听到“我要开始学习C++!”的呐喊,无数次听到“C++太复杂了,我真的学不会”的无奈.Stan Lippman先生曾在<C++ Primer>一书中指出“C++是最为难学的 ...
- vue-cli的工程模板与构建工具
vue-cli的工程模板与构建工具 https://www.cnblogs.com/yinn/p/9712480.html 脚手架vue-cli系列二:vue-cli的工程模板与构建工具 上篇文章我们 ...
- MySQL子查询,派生表和通用表达式
一:子查询 1.介绍 在另一个查询(外部查询)中嵌套另一个查询语句(内部查询),并使用内部查询的结果值作为外部查询条件. 2.子查询在where中 SELECT customerNumber, che ...
- Windows 下 MySql 5.7.20安装及data和my.ini文件的配置(转)
Windows 下 MySql 5.7.20安装及data和my.ini文件的配置 本文通过图文并茂的形式给大家介绍了MySql 5.7.20安装及data和my.ini文件的配置方法. my ...
- linux timer operate
1.gettimeofday() ----> http://www.linuxidc.com/Linux/2012-06/61903.htm (一般)