在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
本文分为两部分,首先说明什么是协变与逆变,之后使用C#自带使用逆变的Action等进行实例演示。
协变与逆变是针对于泛型而言的,为了更加清楚的说明问题,首先我构造两个类如下: class Animal { } class Cat : Animal { } 很简单,Animal为基类,Cat为继承的子类,那么接下来的写法大家一起来分析一下写的是否正确: 1 Animal animal1 = new Cat(); 2 List<Animal> animals = new List<Cat>(); 答案是:第一行的完全正确,第二行是错误的,C#编译器给我们的错误提示为: 也就是说虽然Cat继承了Animal,但是List<Cat>并未继承List<Animal> 我们换一种写法: IEnumerable<Animal> list2 = new List<Cat>();
这样就是对的了,F12查看IEnumerable定义: 那么这个out是什么意思呢?为什么使用了它,就可以写出并不是看左右整体是否是继承关系才能通过编译呢? 泛型前加out它代表的就是协变,T只能作为返回值,不能作为参数,这就是协变 我们编写一个自定义协变,来理解一下到底什么是协变,如何理解,如何记忆: #region 自定义协变 public interface ICustomerListOut<out T> { T Get();//T只能作为返回值,不能作为参数 } public class CustomerListOut<T> : ICustomerListOut<T> { public T Get() { return default(T); } } #endregion 使用协变: // 使用自定义协变 ICustomerListOut<Animal> customerList1 = new CustomerListOut<Animal>(); ICustomerListOut<Animal> customerList2 = new CustomerListOut<Cat>(); //理解成后面实例的实际类型(Cat)必须是左边(Animal)内部扩展的(即继承了左边的类型或接口)(out) 这么理解:右边必须是左边的扩展(因为是out),即右边需要继承或者实现了左边;上方就是右边的Cat继承了左边的Animal;
对于C#委托相比大家都不是很陌生,如Action<T>,Func<T>等,F12查看定义: 那么这个in又是什么意思呢? 在泛型前加in,而且T只能作为方法参数,不能作为返回值,这就是逆变 我们编写一个自定义逆变,来理解一下到底什么是逆变,如何理解,如何记忆: #region 自定义逆变 //在泛型接口的T前面有一个In关键字修饰,而且T只能方法参数,不能作为返回值类型,这就是逆变 public interface ICustomerListIn<in T> { void Show(T t);//T只能作为参数,不能作为返回值 } public class CustomerListIn<T> : ICustomerListIn<T> { public void Show(T t) { } } #endregion 使用: // 使用自定义逆变 ICustomerListIn<Cat> customerListCat1 = new CustomerListIn<Cat>(); ICustomerListIn<Cat> customerListCat2 = new CustomerListIn<Animal>(); //理解成后面实例的实际类型(Animal)必须在左边(Cat)内部已经继承或者实现了的(in) 这么理解:右边必须是左边的基类或者实现的接口(因为是in),即右边需要左边继承或实现了它;上方就是右边的Animal被左边的Cat继承了;
in就是在括号内做参数,out就是出括号做返回值,这样来记。 使用Action<in T>举例子来加深理解的深度: 首先定义两个Action如下: public Action<Animal> an; public Action<Cat> cat; 然后定义两个方法: public void ceshi1(Animal an) { } public void ceshi2(Cat an) { } 我书写如下代码,大家一起来理解一下,看看写的是否对: 1)an+=ceshi1 2)an+=ceshi2 3)cat+=ceshi1 4)cat+=ceshi2 答案是:1.3.4都是对的 2是错的 因为2式中 an是Animal,测试2是Cat,在逆变情形下,需要左边实现或者继承右边 而实际情况是Cat继承了Animal,因此3对,2不对。 杰杰觉得这个很有用,希望跟大家一起分享。
|
请发表评论