学习C#基础进阶之c#泛型知识详解(2)
57下面的代码示例演示客户端代码如何使用泛型 GenericList<T> 类来创建整数列表。只需更改类型参数,即可方便地修改下面的代码示例,创建字符串或任何其他自定义类型的列表:
Code
1class TestGenericList
2{
3 static void Main()
4 {
5 // int is the type argument
6 GenericList<int> list = new GenericList<int>();
7
8 for (int x = 0; x < 10; x++)
9 {
10 list.AddHead(x);
11 }
12
13 foreach (int i in list)
14 {
15 System.Console.Write(i + " ");
16 }
17 System.Console.WriteLine("\nDone");
18 }
19}
20
C#泛型编译机制:
第一轮编译时,编译器只为Stack<T>(栈算法)类型产生“泛型版”的IL代码与元数据-----并不进行泛型类型的实例化,T在中间只充当占位符
JIT编译时,当JIT编译器第一次遇到Stack<int>时,将用int替换“泛型版”IL代码与元数据中的T---进行泛型类型的实例化。
CLR为所有类型参数为“引用类型”的泛型类型产生同一份代码;但如果类型参数为“值类型”,对每一个不同的“值类型”,CLR将为其产生一份独立的代码。
泛型的优点对比:
在公共语言运行库和 C# 语言的早期版本中,通用化是通过在类型与通用基类型 Object 之间进行强制转换来实现的,泛型提供了针对这种限制的解决方案。通过创建泛型类,您可以创建一个在编译时类型安全的集合。
使用非泛型集合类的限制可以通过编写一小段程序来演示,该程序利用 .NET Framework 类库中的 ArrayList 集合类。ArrayList 是一个使用起来非常方便的集合类,无需进行修改即可用来存储任何引用或值类型。
Code
1System.Collections.ArrayList list1 = new System.Collections.ArrayList();
2list1.Add(3);
3list1.Add(105);
4
5System.Collections.ArrayList list2 = new System.Collections.ArrayList();
6list2.Add("It is raining in Redmond.");
7list2.Add("It is snowing in the mountains.");
8
但这种方便是需要付出代价的。添加到 ArrayList 中的任何引用或值类型都将隐式地向上强制转换为 Object。如果项是值类型,则必须在将其添加到列表中时进行装箱操作,在检索时进行取消装箱操作。强制转换以及装箱和取消装箱操作都会降低性能;在必须对大型集合进行循环访问的情况下,装箱和取消装箱的影响非常明显。
另一个限制是缺少编译时类型检查;因为 ArrayList 会将所有项都强制转换为 Object,所以在编译时无法防止客户端代码执行类似如下的操作:
Code
1System.Collections.ArrayList list = new System.Collections.ArrayList();
2// Add an integer to the list.
3list.Add(3);
4// Add a string to the list. This will compile, but may cause an error later.
5list.Add("It is raining in Redmond.");
6
7int t = 0;
8// This causes an InvalidCastException to be returned.
9foreach (int x in list)
10{
11 t += x;
12}