泛型的优点

来源:互联网 发布:csgo网络很卡 编辑:程序博客网 时间:2024/05/23 19:18

一、性能

泛型的一个主要优点是性能。对值类型使用非泛型集合类,在把值类型转换为引用类型和把引用类型转换为值类型时,需要进行装箱和拆箱操作。

下面是System.Collections命名空间中的ArrayList类。ArrayList存储对象,Add()方法定义为需要把一个对象作为参数。因此,要Add一个整数类型的参数,就要进行装箱操作。在读取ArrayList中的值时,要进行拆箱,把对象转换为整数类型。

可以使用类型转换运算符把ArrayList集合的第一个元素赋予变量i1,在访问int类型的变量i2的foreach语句中,也要使用类型转换运算符:

ArrayList list =new ArrayList();list.Add(44);  //boxing - convert a value type to a referece typeint i1 = (int)list[0]; //unboxing - convert a referece type to a value typeforeach(int i2 in list){    Console.WriteLine(i2); //unboxing}

装箱和拆箱操作很容易使用,但性能损失比较大,迭代许多项时尤其如此。

System.Collections.Generic命名空间中的List<T>不使用对象,而是在使用时定义类型。在下面的例子中,List<T>类的泛型类型定义为int,所以int类型在JIT编译器动态生成的类中使用,不再进行装箱和拆箱操作。

List<int> list = new List<int>();list.Add(44);  //no boxing - value types are stored in the List<int>int i1 =list[0];   // no unboxing, no cast neededforeach(int i2 in list){    Console.WriteLine(i2);}


二、类型安全

泛型的另一个特性是类型安全。与ArrayList类一样,如果使用对象,可以在这个集合中添加任意类型。下面的例子在ArrayList类型的集合中添加一个整数、一个字符串和一个MyClass类型的对象:

ArrayList list = new ArrayList();list.Add(44);list.Add("mystring");list.Add(new MyClass());

如果这个集合使用下面的foreach语句迭代,而该foreach语句使用整数元素来迭代,编译器就会编译这段代码,编译时并不会出错。但并不是集合中的所有元素都可以转换为int,所以会出现一个运行异常。

foreach (int i in list){    Console.WriteLine(i);}

错误应尽早发现。在泛型类List<T>中,泛型类型T定义了允许使用的类型。有了List<int>的定义,就只能把整数类型添加到集合中。编译器不会编译这段代码,因为Add()方法的参数无效:

List<int> list = new List<int>();list.Add(44);list.Add("mystirng"); //compile time errorlist.Add(new MyClass());  //compile time error


三、二进制代码的重用

泛型允许更好地重用二进制代码。泛型类可以定义一次,用许多不同的类型实例化。不需要想C++模板那样访问源代码。

例如,System.Collections.Generic 命名空间中的List<T>类用一个int、一个字符串和一个MyClass类型实例化:

List<int> list = new List<int>();list.Add(44);List<string> stringList = new List<string>();stringList.Add("myString");List<MyClass> myClassList = new List<MyClass>

 

四、代码的扩展性

因为泛型的定义会放在程序集中,所以用某个类型实例化泛型类不会再IL代码中复制这些类。但是,在JIT编译器把泛型类编译为内部代码时,会给每一个值类型创建一个新类。引用类型共用一个内部类的所有实现代码。这是因为引用类型在实例化的泛型类中只需要4个字节的内存单元(32位系统),就可以引用一个引用类型。值类型包含在实例化的泛型类的内存中。而每个值类型对内存的要求都不同,所以要为每个值类型实例化一个新类。

五、命名约定

如果在程序中使用泛型,区分泛型类型和非泛型类型会有一定的帮助。下面是泛型类型的命名规则:

  • 泛型类型的名称用字母T作为前缀。
  • 如果没有特殊的要求,泛型类型允许用任意类代替,且只使用一个泛型类型,就可以用字符T作为泛型类型的名称。
public class List<T>{}public class LinkedList<T>{}


如果泛型类型有特定的要求,或者使用了两个或多个泛型类型,就应该给泛型类型使用描述性的名称:

public delegate void EventHandler<TEventArgs>(object sender,TEventArgs e);public delegate TOutput Converter<TInput,TOutput>(TInput from);public class SortedList<TKey,TValue>{}