C# 基础系列–泛型(抗变和协变)

  泛型的抗变和协变是在.NET4.0中才增加, 这对之前的接口的一个不错的扩展。抗变和协变是指针对参数和返回值的类型转换。

  在.NET中 参数类型是协变,返回值是抗变。

  不要废话了,先定义两个我们例子用的实体类—基类  RectangleBase  派生类–Rectangle 

 

 public class RectangleBase      {        public int ID { get; set; }    }    public class Rectangle : RectangleBase    {        public string Name { get; set; }    }

 

如果有个方法 public void Display(RectangleBase  r)  我们传入一个 Rectangle 的实体,那么就是一个参数类型的协变

如果有个方法public RectangleBase   GetRectangle()  我们这里 RectangleBase b = GetRectangle() 那么这就是方法返回类型的抗变。

 在4.0之前,泛型接口是不拥有想上面类的便利性。很幸运,微软在 4.0对泛型接口扩展这写!

 

协变


 

  如果泛型接口中有关键字 out的,那个这个泛型接口就是协变。这个就定义了这个接口只能返回类型只能是T。

我们先定义一个接口

public interface IIndex<out T>    {        T this[int index] { get; }        int Count { get; }    }

  我们的实现类:

 

public class RectangleCollection : IIndex<Rectangle>    {        List<Rectangle> list = new List<Rectangle>();        public Rectangle this[int index]        {            get             {                if (index < 0 || index > Count)                    throw new ArgumentOutOfRangeException("index");                return list[index];            }        }        public int Count        {            get { return list.Count; }        }       public  void  Add(Rectangle value)        {                 list.Add(value);        } }

  

  然后我们在控制台是这样:

var list = new RectangleCollection();            list.Add(new Rectangle { ID = 1, Name = "111" });            list.Add(new Rectangle { ID = 2, Name = "222" });            list.Add(new Rectangle { ID = 3, Name = "33" });            IIndex<RectangleBase> Bas = list;            for (int i = 0; i < Bas.Count; i++)            {                Console.WriteLine(Bas[i].ID);               }            Console.Read();  

  

 

  协变很简单吧。。。如果你吧关键字out 去掉后,编译器很快就会个告诉你  IIndex<RectangleBase> Bas = list; 错误。因为你没有告诉他 这个T是可以变的

 

抗变


 

   如果泛型接口有关键字in ,那么表示这个泛型接口是可以抗变的。这样,接口也只能把泛型类型T用作方法的输入。

 

 定义泛型抗变的 接口

public interface IDisplay(in T){        void Show(T item);}

  抗变类:

public class RectangleDisplay:  IDisplay<RectangleBase>{       public void Show(RectangBase item)      {            Console.WrileLine(item.ID);    }}

  

 这篇写的不是很好,因为我自己也不是吃的很透,今天在朋友的稍稍点拨下,算是有点 理解这个了。第一次接触这个东西到现在又一年多了,今天才理解点,惭愧惭愧。

  

本文链接



You must enable javascript to see captcha here!

Copyright © All Rights Reserved · Green Hope Theme by Sivan & schiy · Proudly powered by WordPress

无觅相关文章插件,快速提升流量