主要的内容:
<1>.原理性的东西----” 泛型的协变和逆变 “
<2>.以及常用的接口----” IEnumerable 及其泛型版的IEnumerable<out T> “
<泛型的协变与逆变|泛型修饰符‘out’与‘in’>
先知道协变和逆变主要是用在泛型的接口和委托上就可以了,下面我们通过一个例子来看看:
我们知道接口是可以体现多态的,当然接口体现的多态注重的功能上的多态,这和抽象类不同,抽象类更注重的是建立在血缘关系上的多态。
知道接口是可以体现多态的之后,我们来看看一个相关的例子--
实例:鸟和飞机都会飞,把飞定义成一个接口,在定义2个类
public interface IFlyable { void fly(); } class Bird:IFlyable { public void fly() { Console.WriteLine("鸟儿飞!"); } } class Plane:IFlyable { public void fly() { Console.WriteLine("飞机飞!"); } }
下面看看接口体现的多态性:
IFlyable ifly; ifly = new Bird(); ifly.fly(); ifly = new Plane(); ifly.fly();
运行结果:
鸟儿飞!
飞机飞!
了解了接口的多态性后我们再来看一个例子:
这里定义了2个类 Animal 和 Cat (Cat继承了Animal)
public class Animal { } public class Cat:Animal { }
继续往下看:
Cat cat = new Cat();
下面这句代码,cat向animal转,子类向父类转换,这时cat会隐式转换为animal 我们说“儿子像父亲” 这是完全可以理解的
Animal animal = cat;
但是 说”父亲像儿子“ 这是说不过去的 ,但是有的时候如果儿子坑爹,强制转换了一下还是可以的
cat = (Cat)animal;
(协变)
List<Cat> catArray = new List<Cat>(); List<Animal> animalArray = catArray;
如果是上面说的类,这样写是可以的,但是这里是会报错的 如图
继续往下看 这样写却可以:
IEnumerable<Cat> lCat = new List<Cat>(); IEnumerable<Animal> lAnimal = lCat;
对 IEnumerable<Cat> 转到定义 如图 我们发现这里多了一个 “out” 关键字
概念引入:
1.对于泛型类型参数,out 关键字指定该类型参数是协变的。 可以在泛型接口和委托中使用 out 关键字。“协变”是指能够使用与原始指定的派生类型相比,派生程度更大的类型。
时间: 2024-10-16 10:26:14