泛型

 

  这两天又看了一些关于变体(协变和逆变)方面的博文,看的时候感觉的确讲的不错,很好理解,但看多了就会发现是越看越晕啊。以前也有做过这方面的总结,但总是过段时间就会脑子里一片空白,这该不会是太极剑的最高境界吧,呵呵,开个小玩笑。不过得先理解泛型

  个人映像中的泛型:1.方法有输入参数(也可以有类型参数),泛型有类型参数

             2.泛型使用特定的类型代替类型参数

           3.泛型可以实现类型安全

             4.泛型可以实现代码重用

从ArrayList到List<T>

  var list = new ArrayList();
   list.Add(1);
   foreach (int obj in list) {
       Console.WriteLine(obj);
   }

  现在看看ArrayList的源码,找到 Add 这个方法:,这说明ArrayList存储的是对象,Add方法定义为需要把一个对象作为参数,所以要装箱一个整数类型,显然读取时要拆箱。装箱和拆箱使性能损失比较大。

  好吧,那我用来存储一个对象(引用类型)呢?

  public class Person {
        public string Say() {
            return "I am a nice man";
        }
    }
 var list = new ArrayList();
 list.Add(new Person());
  foreach (Person obj in list) {
    Console.WriteLine(obj.Say());
 }  

Ok,很好用,没有问题。但如果不慎像下面这样使用,在最后若传了个Japanese实例

public class Japanese{
  ...
}
  var list = new ArrayList();
  list.Add(new Person());
  list.Add(new Japanese());
  foreach (Person obj in list) {
     Console.WriteLine(obj.Say());
 }  

  编译是能通过的(Add方法只负责接受Object,foreach为运行时迭代),但运行时,不幸抛异常了(Person和Japanese好像没有继承关系吧,至少在我的代码里)。foreach元素使用Person类型来迭代,很显然突然冒出来个Japanese,当然不知该如何是好。

  C#是类型安全的语言,编译器可以捕捉到潜在的错误,而不是在运行时才以异常的方式呈现。显然我们这里需要一个类型参数,这个参数会告知编译器只接受某某类型的输入参数。请看泛型版本

  List<Person> pList = new List<Person>();
  pList.Add(new Person());
  foreach (Person obj in list)
  {
    Console.WriteLine(obj.ToString());
  }    

  使用Add方法添加元素时只接受Person类型,有截图、有真相

泛型可以实现代码重用

   现在要用到一个存放Person对象的集合类,可以用下面的代码  

public class PeronList :IEnumerable{

        private int personCount;
        private ArrayList personArray;

        public PeronList(){
            this.personCount = 0;
            this.personArray = new ArrayList();
        }

        public int PersonCount
        {
            get{return this.personCount;}
            private set{this.personCount=value;}
        }

        public void Append(Person _Person){
            this.personCount++;
            this.personArray.Add(_Person);
        }

        public Person indexOf(int index) {
            return (Person)this.personArray[index];
        }

        public IEnumerator GetEnumerator()
        {
            for (int i = 0; i < this.personCount; i++)
            {
                yield return this.indexOf(i);
            }
        }
    }

  是轻松完成了任务,且类型安全。假若又需要一个存放Animal对象的集合,So easy,这回不用动脑子了,直接Copy,Paste,then修该几个有类型修改的地方。但下回、下下回呢,不能总是麻烦自己的双手和浪费宝贵的时间吧,再说改动过程中又极有可能出现失误。

  就不能有什么一劳永逸的解决办法么?当然是使用泛型List<T>啦,使用方式上面已经有啦。

泛型的使用

   1.泛型类:泛型类使用类型参数来实现C#的类型安全和代码重用

   2.泛型约束:是对类型参数的范围约束

     3.泛型方法:类型参数用方法声明来定义,泛型方法是由于泛型没有必要应用于整个类,一般应用在某个静态方法中使用,同样泛型方法也可以有泛型约束

总结

  泛型还是很好用的,使用方便,可以减少重复代码,实现类型安全,使用List<T>代替ArrayList是必然。在JIT编译器把泛型编译为本地代码时,会给每个类型参数为值类型的创建一个新类,为引用类型共享同一个本地类的所有实现代码。

 

posted @ 2013-01-15 01:25  Frozen.Zhang  阅读(625)  评论(1编辑  收藏  举报