代码改变世界

泛型学习总结

2008-11-15 19:15  yearN  阅读(448)  评论(0)    收藏  举报

  泛型使您可以按照泛型操作的精确的数据类型定制方法、类、结构或接口。例如,您可以使用 Dictionary 泛型类并指定允许的键类型和允许的值类型,而不使用允许任何键类型和值类型的 Hashtable 类。泛型的优点包括提高的代码可重用性和类型安全性。
   泛型主要用的命名空间有:System.Collections.Generic和System.Collections.ObjectModel。
  C#泛型和C++模板的区别是:C++模板是静态的,容易引起的问题是代码膨胀和类型安全问题,而C#泛型则恰好解决了这一问题。C#泛型对于引用类型是代码共享的,对于值类型和C++模板大致相同(个人观点)。
来看一个泛型的例子:
// type parameter T in angle brackets
public class GenericList<T>
{
// The nested class is also generic on T
private class Node
{
// T used in non-generic constructor
public Node(T t)
{
next = null;
data = t;
}

private Node next;
public Node Next
{
get { return next; }
set { next = value; }
}

// T as private member data type
private T data;

// T as return type of property
public T Data
{
get { return data; }
set { data = value; }
}
}

private Node head;
// constructor
public GenericList()
{
head = null;
}

// T as method parameter type:
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;
}
}
}
下面的代码示例演示客户端代码如何使用泛型 GenericList<T> 类来创建整数列表。只需更改类型参数,即可方便地修改下面的代码示例,创建字符串或任何其他自定义类型的列表:
class TestGenericList
{
static void Main()
{
// int is the type argument
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");
}
}
这是MSDN上的一个示例,说明了泛型的简单用法。其实C#为我们封装了很多泛型类和方法。
我们常用的集合类有:ArrayList、HashTable、Stack、Queue、SortedList等。
C#为我们提供的泛型版本是:List<T>、Dictionary<key,value>、Stack<T>、Queue<T>、SortedList<T>等。
O'Reilly 出版的《C# Cookbook》一书中,给出了何时使用泛型的一个解决方案(转载自博客园一个园友翻译的文章中):
决定在何时何地使用泛型,您需要考虑以下几件事件:

  1. 您所使用的类型是否包含或操作未指定的数据类型(如集合类型)?如果是这样,如果是这样,创建泛型类型将能提供更多的好处。如果您的类型只操作单一的指定类型,那么就没有必要去创建一个泛型类。
  2. 如果您的类型将操作值类型,那么就会产生装箱和拆箱操作,就应该考虑使用泛型来防止装箱和拆箱操作。
  3. 泛型的强类型检查有助于快速查找错误(也就是编译期而非运行期),从而缩短bug修复周期。
  4. 在编写多个类操作多个数据类型时是否遭遇到“代码膨胀”问题(如一个ArrayList只存储StreamReaders而另一个存储StreamWriters)?其实编写一次代码并让它工作于多个数据类型非常简单。
  5. 泛型使得代码更为清晰。通过消除代码膨胀并进行强制检查,您的代码将变得更易于阅读和理解。
泛型有四种约束:基类约束、接口约束、构造器约束、值类型/引用类型约束。
下面是载自李建忠老师(C#锐利系列课程中泛型简介中的内容)

 

  1. 泛型接口的参数要么已实例化,要么来源于实现类声明的类型参数。
  2. 泛型方法即可以包含在泛型类型中,也可以包含在非泛型类型中。
  3. 合法的重写方法,约束被默认继承,在重写方法中,不能为其添加额外的约束。

泛型接口示例:
public class Node<T> : IComparable<Node<T>> where T : IComparable<T>
这句代码定义了一个泛型Node,它操作类型T。Node中的T实现了IComparable<T>接口,这意味着两个Node的T可以进行对比。Node类通过约束(where T : IComparable<T>)来操作那些实现了IComparable接口的类型。因此您可以使用任何类型来替代T,只要那种类型实现了IComparable接口