1、泛型概述
- 泛型可将具体类型的指定推迟到客户端代码声明并实例化类的时候。
- 使用泛型类型可以最大限度地重用代码、保护类型的安全以及提高程序的性能。
- 泛型最常见的用途是创建集合类。
- NET Framework 类库在 System.Collections.Generic 命名空间中包含几个泛型集合类。应尽可能地使用这些类来代替普通的类,如 System.Collections 命名空间中的 ArrayList等集合类。
2.泛型优点
- 通过创建泛型类,您可以创建一个在编译时类型安全的集合(编译时进行类型检查)。
- 代码说明:
代码
System.Collections.ArrayList list = new System.Collections.ArrayList();.
list.Add(3);
list.Add("It is raining in Redmond.");
int t = 0;
foreach (int x in list)//编译是这里不抛异常,至到运行时报错
{
t += x;
}
如上代码,尽管将字符串和 int组合在一个 ArrayList 中的做法在创建异类集合时是完全合法的,因为 ArrayList 将把所有项都强制转换为 Object, 但这种做法更可能产生编程错误,并且直到运行时才能检测到此错误。
- 通过创建泛型类,可以提高程序的性能,避免不必要的强制转换、装箱、拆箱操作。
- 代码说明:
代码
System.Collections.ArrayList list1 = new System.Collections.ArrayList();
list1.Add(3);
list1.Add(105);
System.Collections.ArrayList list2 = new System.Collections.ArrayList();
list2.Add("It is raining in Redmond.");
list2.Add("It is snowing in the mountains.");
上例代码说明ArrayList 是一个使用起来非常方便的集合类,无需进行修改即可用来存储任何引用或值类型。但这种方便是需要付出代价的。添加到 ArrayList 中的任何引用或值类型都将隐式地向上强制转换为 Object。如果项是值类型,则必须在将其添加到列表中时进行装箱操作,在检索时进行拆箱操作。强制转换以及装箱和拆箱操作都会降低性能;在必须对大型集合进行循环访问的情况下,装箱和拆箱的影响非常明显。
3. 泛型的类型参数
类型参数是客户端在实例化泛型类型的变量时指定的特定类型的占位符。(如下示例)
代码
public class GenericList<T> //T为泛型的类型参数,但在客户端代码中指定T的具体类型时,泛型中的所有T都替换为具体的类型
{
//定义一个嵌套类
private class Node
{
public Node(T t)
{
next = null;
data = t;
}
private Node next;
public Node Next
{
get { return next; }
set { next = value; }
}
private T data;
public T Data
{
get { return data; }
set { data = value; }
}
}
private Node head;//声明一个嵌套类的变量
public GenericList()
{
head = null;
}
//泛型类的添加成员方法
public void AddHead(T t)
{
Node n = new Node(t);
n.Next = head;
head = n;
}
//用于泛型类集合的遍历
public IEnumerator<T> GetEnumerator()
{
Node current = head;
while (current != null)
{
yield return current.Data;
current = current.Next;
}
}
}
代码
static void Main(string[] args)
{
GenericList<int> list = new GenericList<int>();
for (int x = 0; x < 10; x++)
{
list.AddHead(x);
}
foreach (int i in list)
{
System.Console.Write(i + " ");
}
System.Console.WriteLine("\nDone");
Console.Read();
4. 泛型和数组
在 C# 2.0 中,下限为零的一维数组自动实现 IList<T>。这使您可以创建能够使用相同代码循环访问数组和其他集合类型的泛型方法。如下示例
代码
class Program
{
static void Main()
{
int[] arr = { 0, 1, 2, 3, 4 };
List<int> list = new List<int>();
for (int x = 5; x < 10; x++)
{
list.Add(x);
}
ProcessItems<int>(arr);
ProcessItems<int>(list);
}
static void ProcessItems<T>(IList<T> coll)
{
foreach (T item in coll)
{
System.Console.Write(item.ToString() + " ");
}
System.Console.WriteLine();
}
}