泛型类
泛型类封装了不针对任何特定数据类型的操作。泛型类常用于容器类,如链表、哈希表、栈、队列、树等等。这些类中的操作,如对容器添加、删除元素,不论所存储的数据是何种类型,都执行几乎同样的操作。
对大多数情况,推荐使用.NET框架2.0类库中所提供的容器类。有关使用这些类的详细信息,请参见基础类库中的泛型。
通常,从一个已有的具体类来创建泛型类,并每次把一个类型改为类型参数,直至达到一般性和可用性的最佳平衡。当创建你自己的泛型类时,需要重点考虑的事项有:
l 哪些类型应泛化为类型参数。一般的规律是,用参数表示的类型越多,代码的灵活性和复用性也就越大。过多的泛化会导致代码难以被其它的开发人员理解。
l 如果有约束,那么类型参数需要什么样约束。一个良好的习惯是,尽可能使用最大的约束,同时保证可以处理所有需要处理的类型。例如,如果你知道你的泛型类只打算使用引用类型,那么就应用这个类的约束。这样可以防止无意中使用值类型,同时可以对T使用as运算符,并且检查空引用。
l 把泛型行为放在基类中还是子类中。泛型类可以做基类。同样非泛型类的设计中也应考虑这一点。泛型基类的继承规则 。
l 是否实现一个或多个泛型接口。例如,要设计一个在基于泛型的容器中创建元素的类,可能需要实现类似IComparable<T>的接口,其中T是该类的参数。
泛型概述中有一个简单泛型类的例子。
类型参数和约束的规则对于泛型类的行为(behavior)有一些潜在的影响,——尤其是对于继承和成员可访问性。在说明这个问题前,理解一些术语十分重要。对于一个泛型类Node<T>,客户代码既可以通过指定一个类型参数来创建一个封闭构造类型(Node<int>),也可以保留类型参数未指定,例如指定一个泛型基类来创建开放构造类型(Node<T>)。泛型类可以继承自具体类、封闭构造类型或开放构造类型
// concrete type class Node<T> : BaseNode //closed constructed type class Node<T> : BaseNode<int> //open constructed type class Node<T> : BaseNode<T>
非泛型的具体类可以继承自封闭构造基类,但不能继承自开放构造基类。这是因为客户代码无法提供基类所需的类型参数。
//No error. class Node : BaseNode<int> //Generates an error. class Node : BaseNode<T>
泛型的具体类可以继承自开放构造类型。除了与子类共用的类型参数外,必须为所有的类型参数指定类型,如下代码所示:
//Generates an error. class Node<T> : BaseNode<T, U> {…} //Okay. class Node<T> : BaseNode<T, int>{…}
继承自开放结构类型的泛型类,必须指定:从开放构造类型继承的泛型类必须指定必须指定作为基本类型约束的超集或暗示的约束:
class NodeItem<T> where T : IComparable<T>, new() {…} class MyNodeItem<T> : NodeItem<T> where T : IComparable<T> , new(){…}
泛型类型可以使用多种类型参数和约束,如下:
class KeyType<K,V>{…} class SuperKeyType<K,V,U> where U : IComparable<U>, where V : new(){…}
开放结构和封闭构造类型型可以用作方法的参数:
void Swap<T>(List<T> list1, List<T> list2){…} void Swap(List<int> list1, List<int> list2){…}