5
{
t += x;
}
虽然这样完全合法,并且有时是有意这样创建一个包含不同类型元素的容器,但是把
string 和 int 变量放在一个 ArrayList 中,几乎是在制造错误,而这个错误直到运行的时
候才会被发现。
在 1.0 版和 1.1 版的 C#语言中,你只有通过编写自己的特定类型容器,才能避免.NET
框架类库的容器类中泛化代码(generalized code)的危险。当然,因为这样的类无法被
其他的数据类型复用,也就失去泛型的优点,你必须为每个需要存储的类型重写该类。
ArrayList 和其他相似的类真正需要的是一种途径,能让客户代码在实例化之前指定所需
的特定数据类型。这样就不需要向上类型转换为 Object,而且编译器可以同时进行类型检
查。换句话说,ArrayList 需要一个类型参数。这正是泛型所提供的。在
System.Collections.Generic 命名空间中的泛型 List<T>容器里,同样是把元素加入容
器的操作,类似这样:
The .NET Framework 2.0 way of creating a list
List<int> list1 = new List<int>();
//No boxing, no casting:
list1.Add(3);
//Compile-time error:
list1.Add("It is raining in Redmond.");
与 ArrayList 相比,在客户代码中唯一增加的 List<T>语法是声明和实例化中的类型参
数。代码略微复杂的回报是,你创建的表不仅比 ArrayList 更安全,而且明显地更加快
速,尤其当表中的元素是值类型的时候。
三、泛型类型参数
在泛型类型或泛型方法的定义中,类型参数是一个占位符(placeholder),通常为一
个大写字母,如 T。在客户代码声明、实例化该类型的变量时,把 T 替换为客户代码所指
定的数据类型。泛型类,如泛型概述中给出的 MyList<T>类,不能用作 as-is,原因在于
它不是一个真正的类型,而更像是一个类型的蓝图。要使用 MyList<T>,客户代码必须
在尖括号内指定一个类型参数,来声明并实例化一个已构造类型(constructed type)。
这个特定类的类型参数可以是编译器识别的任何类型。可以创建任意数量的已构造类型实
例,每个使用不同的类型参数,如下:
MyList<MyClass> list1 = new MyList<MyClass>();