c# 逆变 协变的理解
2015-06-16 14:54
495 查看
逆变和协变是C# 4.0出来的,个人认为这是对泛型的扩充,让C#的语法更加灵活,方便重用。只有泛型接口和泛型委托可以是协变的或逆变的。
泛型中有out in关键字,用于定义此泛型是遵守逆变还是协变。out限制了泛型只能用于返回值,in限制了泛型只能用于参数。
之前的泛型是可以指定对某一类操作,但是无法把类的子类,父类赋值转换。有了逆变和协变,实现了泛型类的父类子类的转换。
协变 (covariant)关键字是out,out限制了泛型只能用于返回值
现在我们有Animal父类,Dog, Cat子类
但现在我们有这样的方法
的工作。这样可以减少了我们的代码量,让程序更灵活。
逆变(contravariant)关键字是in,in限制了泛型只能用于参数
下面以Action<in T>为例
编译通过,因为 Action支持逆变,类型向下转换
作用:我个人肤浅的理解,之前的泛型是可以指定对某一类操作,但是无法把类的子类,父类赋值转换。有了逆变和协变,实现了泛型类的父类子类的转换。目的是为了增加语言的灵活性和能力。使泛型和委托的功能更加强大。
泛型中有out in关键字,用于定义此泛型是遵守逆变还是协变。out限制了泛型只能用于返回值,in限制了泛型只能用于参数。
之前的泛型是可以指定对某一类操作,但是无法把类的子类,父类赋值转换。有了逆变和协变,实现了泛型类的父类子类的转换。
协变 (covariant)关键字是out,out限制了泛型只能用于返回值
示例代码如: public interface IEnumerable<out T> public static void Main() { Dog aDog = new Dog(); Animal aAnimal = aDog; IEnumerable<Dog> someDogs = new List<Dog>(); IEnumerable<Animal> someAnimals = someDogs; }
现在我们有Animal父类,Dog, Cat子类
public class Animal { public string type; public Animal() { type = "Animal"; } } public class Dog : Animal { public Dog() { type = "dog"; } } public class Cat : Animal { public Cat() { type = "Cat"; } }如果我们使用List<T>泛型,那我们在List<Animal>和List<Cat>是不能互相转换的。下面的代码是编译不通过的
List<Animal> animalList = new List<Dog>();如果要实现这个转换必须要使用如下的方法
animalList = dogList.Select(o => (Animal)o).ToList();
但现在我们有这样的方法
public void PrintAnimals(IEnumerable<Animal> animals) { foreach (var item in animals) { Console.WriteLine(item.type); } }就可以能传递List<Cat>了, 也能传递List<Animal>,因为IEnumerable<out T>有out标记,表示可以协变,所以编译通过。但是在内部,IL还是帮我做了一个个元素依次转换
的工作。这样可以减少了我们的代码量,让程序更灵活。
逆变(contravariant)关键字是in,in限制了泛型只能用于参数
下面以Action<in T>为例
public delegate void Action<in T> public static void Main() { Action<Animal> actionAnimal = new Action<Animal>(a => {/*让动物叫*/ }); Action<Dog> actionDog = actionAnimal; actionDog(aDog); }
编译通过,因为 Action支持逆变,类型向下转换
作用:我个人肤浅的理解,之前的泛型是可以指定对某一类操作,但是无法把类的子类,父类赋值转换。有了逆变和协变,实现了泛型类的父类子类的转换。目的是为了增加语言的灵活性和能力。使泛型和委托的功能更加强大。
相关文章推荐
- c#调用COM组件
- JAVA泛型—— 3fe8 转
- JAVA泛型详解——转
- C#实现把指定数据写入串口
- C#中抽象方法与虚拟方法的区别
- c#中虚函数的相关使用方法
- C#实现多线程的同步方法实例分析
- C#中尾递归的使用、优化及编译器优化
- C#通用邮件发送类分享
- C#中this的用法集锦
- C#中Equality和Identity浅析
- C#生成饼形图及添加文字说明实例代码
- C#判等对象是否相等的方法汇总
- C#简单的向量用法实例教程
- C#托管堆对象实例包含内容分析
- C#实现按照指定长度在数字前补0方法小结
- C#虚方法的声明和使用实例教程
- C#获取文件夹及文件的大小与占用空间的方法
- C#定义简单的反射工厂实例分析
- C#数字图象处理之肤色检测的方法