• 泛型


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

      个人映像中的泛型: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编译器把泛型编译为本地代码时,会给每个类型参数为值类型的创建一个新类,为引用类型共享同一个本地类的所有实现代码。

  • 相关阅读:
    Java 第一章 初识Java
    Tomcat基础教程(三)
    Tomcat基础教程(二)
    Web Service相关工具的配置
    分布式版本控制系统Git的安装与使用
    个人项目小学四则运算 “软件”之初版
    结对项目四则运算 “软件”之升级版
    第一篇作业准备
    Linux常用命令入门文件、网络、系统及其他操作命令
    MySql5.7默认生成的密码无法正常登陆
  • 原文地址:https://www.cnblogs.com/frozenzhang/p/generic.html
Copyright © 2020-2023  润新知