一个简单例子理解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 ...
随机推荐
- VCForPython27.msi安装后, 还显示error: Unable to find vcvarsall.bat
C:\Users\zpc\AppData\Local\Programs\Common\Microsoft\Visual C++ for Python\9.0\VC 增加环境变量: SET VCPYTH ...
- Linux内核源码分析--内核启动之(1)zImage自解压过程(Linux-3.0 ARMv7) 【转】
转自:http://blog.chinaunix.net/uid-25909619-id-4938388.html 研究内核源码和内核运行原理的时候,很总要的一点是要了解内核的初始情况,也就是要了解内 ...
- Linux 串口、usb转串口驱动分析(2-1) 【转】
转自:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=26807463&id=4186851 Linux 串口.usb转 ...
- free vmstat查看内存及系统调优【转】
内存查看 查看内存是否存在瓶颈,使用top指令看比较麻烦,而free命令更为直观: [/home/weber#]free total used free shared buffers cached M ...
- Tomcat优化步骤【转】
一.Tomcat的缺省是多少,怎么修改 Tomcat的缺省端口号是8080.修改Tomcat端口号:1.找到Tomcat目录下的conf文件夹2.进入conf文件夹里面找到server.xml文件3. ...
- 002_CentOS-6.4-x86_64安装包的说明
http://mirrors.sohu.com/centos/6.6/isos/x86_64/?qq-pf-to=pcqq.group //souhu镜像下载地址 0_README.txt 25-Oc ...
- nginx + php + centos 6.3
2014年2月7日 22:34:52 PHP 5.5.9 http://cn2.php.net/distributions/php-5.5.9.tar.bz2 nginx 1.5.10 http:// ...
- PS 切图、抠图
PS切图https://www.cnblogs.com/xiongmanli/p/6079172.html https://tech.youzan.com/cut-boy/?hmsr=toutiao. ...
- poj 3468 线段树 成段增减 区间求和
题意:Q是询问区间和,C是在区间内每个节点加上一个值 Sample Input 10 51 2 3 4 5 6 7 8 9 10Q 4 4Q 1 10Q 2 4C 3 6 3Q 2 4Sample O ...
- 【算法】后缀自动机(SAM) 初探
[自动机] 有限状态自动机的功能是识别字符串,自动机A能识别字符串S,就记为$A(S)$=true,否则$A(S)$=false. 自动机由$alpha$(字符集),$state$(状态集合),$in ...