基础【泛型】-----(协变,逆变1)------(转)
“协变”是指能够使用与原始指定的派生类型相比,派生程度更大的类型。
“逆变”则是指能够使用派生程度更小的类型。
解释的很正确,大致就是这样,不过不够直白。
直白的理解:
“协变”->”和谐的变”->”很自然的变化”->string->object :协变。
“逆变”->”逆常的变”->”不正常的变化”->object->string 逆变。
上面是个人对协变和逆变的理解,比起记住那些派生,类型,原始指定,更大,更小之类的词语,个人认为要容易点。
实例:两个类
1 // 父类:动物 2 public class Animal 3 { } 4 5 // 子类:狗 6 public class Dog : Animal 7 { }
1、Dog继承Animal ,可以Animal animal = dog; 那么List<Animal> listAniaml = listDog;如何实现呢
1 public static void MainClass() 2 { 3 4 Dog dog = new Dog(); 5 // Dog继承自Animal,会隐式的转变为Animal; 6 // 子类对象可以创建为它的父类对象(自动转换的) 7 Animal animal = dog; 8 9 List<Dog> listDog = new List<Dog>(); 10 // List<Dog> 不继承List<Animal> ,会出错 11 //List<Animal> listAniaml = listDog; 12 13 // 方法一: 14 List<Animal> lstAnimal2 = listDog.Select(d => (Animal)d).ToList(); 15 16 // 方法二: 17 IEnumerable<Dog> someDogs = new List<Dog>(); 18 IEnumerable<Animal> someAnimals = someDogs; 19 }
其中方法二:IEnumerable<T> (T为协变)
因为T只能做结果返回,所以T不会被修改,编译器就可以推断下面的语句强制转换合法,所以可以转换。
2、一个子类Dog可以创建成为它的父类Animal 对象,那如果实现一个父类创建成为它的一个子类对象呢?
因为协变和逆变的英文太复杂了,并没有体现协变和逆变的不同,但是out 和 in 却很直白。out: 输出(作为结果),in:输入(作为参数)。所以如果有一个泛型参数标记为out,则代表它是用来输出的,只能作为结果返回,而如果有一个泛型参数标记为in,则代表它是用来输入的,也就是它只能作为参数。
1 public interface IMyList<in T> 2 { 3 void ChangeT(T t); 4 } 5 6 public class MyList<T> : IMyList<T> 7 { 8 public void ChangeT(T t) 9 { 10 //Change T 11 } 12 } 13 14 // 编译成功,因为in代表了逆变,所以可以编译成功! 15 IMyList<Animal> myAnimals = new MyList<Animal>(); 16 IMyList<Dog> myDogs = myAnimals;