协变和逆变之疑问
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了协变和逆变之疑问相关的知识,希望对你有一定的参考价值。
前言
关于协变和逆变已经有很多园友谈论过了,学习时也参考过园友们的文章,非常之到位!这个问题可能对您而言很简单,若有解释,请告知,在此感谢。高手绕道!
既然是标题是协变和逆变,还是先给个公认的msdn概念吧。说完概念直接进入问题区。
概念
协变:是指能够使用与原始指定的派生类型相比,派生程度更大的类型。
逆变:则是指能够使用派生程度更小的类型。
问题
请看代码
1 public class Employee2 {3 4 }5 6 public class Programmer : Employee7 {8 9 }
再看定义的接口以及实现
1 interface ISalary<out T> 2 { 3 T pay(); 4 void otherpay(T t); 5 } 6 7 public class BaseSalaryCounter<T> : ISalary<T> 8 { 9 public T pay()10 {11 return default(T);12 }13 14 public void otherpay(T t)15 {16 17 }18 }
再在控制台中调用
ISalary<Programmer> pro = new BaseSalaryCounter<Programmer>(); ISalary<Employee> emp = pro;
毫无疑问出现错误,如下:【注】若不明白错误原因请参考园友LoveJenny文章
但是现在我这样做,注意下面红色部分!
1 interface ISalary<out T> 2 { 3 T pay(); 4 void otherpay<T>(T t); 5 } 6 7 public class BaseSalaryCounter<T> : ISalary<T> 8 { 9 public T pay()10 {11 return default(T);12 }13 14 public void otherpay<T>(T t)15 {16 17 }18 }
再在控制台调用就生成成功了!不是说的out着重于的是返回值,而in着重于的是作为参数吗,这里有个无返回值并且有参数的方法otherpay()方法,根据上面第一个是错误的,修改成这样怎么就对了呢??怎么没出现上图错误呢???才疏学浅,百思不得其解,希望得到令人信服的解释!
问题解决
【注】泛型参数T在被套另一动作后其可变性会被扭转。
总结
(1)引入协变(out)和逆变(in)是为了解决类型安全。
(2)若泛型参数处于输出的位置,那它的协变性是类型安全的。
(3)若泛型参数处于输入的位置,则它的逆变性一般是类型安全的。(说的是一般情况下,更多请参考资料)
补充
逆变(in)典型用法
1 /*定义接口*/ 2 public interface IMyComparable<in T> 3 { 4 int Compare(T other); 5 } 6 /*Employee为基类并实现其接口*/ 7 public class Employee : IMyComparable<Employee> 8 { 9 public string Name { get; set; }10 public int Compare(Employee other)11 {12 return Name.CompareTo(other.Name);13 }14 }15 16 /*Programmer继承Employee并实现其接口*/17 public class Programmer : Employee, IMyComparable<Programmer>18 {19 20 public int Compare(Programmer other)21 {22 return Name.CompareTo(other.Name);23 }24 }25 26 /*Manager继承Employee*/27 public class Manager : Employee28 {29 30 }31 32 /*定义方法*/33 34 static void Test<T>(IMyComparable<T> t1, T t2)35 {36 37 }38 39 /*调用*/40 41 Programmer p = new Programmer() { Name = "Mike" };42 Manager m = new Manager() { Name = "Steve" };43 Test(p, m);
以上是关于协变和逆变之疑问的主要内容,如果未能解决你的问题,请参考以下文章