首页 > 代码库 > C#泛型(三)

C#泛型(三)

主要的内容:

      <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 关键字。“协变”是指能够使用与原始指定的派生类型相比,派生程度更大的类型。

 

C#泛型(三)