Sophie+Software=Wonderful
何时使用泛型集合
通常情况下,建议您使用泛型集合,因为这样可以获得类型安全的直接优点而不需要从基集合类型派生并实现类型特定的成员。此外,如果集合元素为值类型,泛型集合类型的性能通常优于对应的非泛型集合类型(并优于从非泛型基集合类型派生的类型),因为使用泛型时不必对元素进行装箱。
下面的泛型类型对应于现有的集合类型:
· Dictionary 是对应于 Hashtable 的泛型类。
· Collection 是对应于 CollectionBase 的泛型类。Collection 可以用作基类,但是与 CollectionBase 不同的是它不是抽象的,因而更易于使用。
· ReadOnlyCollection 是对应于 ReadOnlyCollectionBase 的泛型类。ReadOnlyCollection 不是抽象的,它具有一个构造函数,该构造函数使其更易于将现有的 List 公开为只读集合。
· Queue、Stack 和 SortedList 泛型类分别对应于与其同名的非泛型类。
其他类型
有几种泛型集合类型没有对应的非泛型类型:
· LinkedList 是一个通用链接列表,它提供运算复杂度为 O(1) 的插入和移除操作。
· SortedDictionary 是一个排序的字典,其插入和检索操作的运算复杂度为 O(log n),这使得它成为 SortedList 的十分有用的替代类型。
· KeyedCollection 是介于列表和字典之间的混合类型,它提供了一种存储包含自己键的对象的方法。
其他功能
一些泛型类型具有在非泛型集合类型中没有的功能。例如,List 类(对应于非泛型 ArrayList 类)具有许多接受泛型委托(如允许指定搜索列表的方法的 Predicate 委托、表示操作每个列表元素的 Action 委托和允许定义类型之间转换的 Converter 委托)的方法。
List 类允许指定您自己的用于排序和搜索列表的 IComparer 泛型接口实现。SortedDictionary 和 SortedList 类也具有此功能,此外还允许在创建集合时指定比较器。类似地,Dictionary 和 KeyedCollection 类允许您指定自己的相等比较器。泛型类和泛型方法同时具备可重用性、类型安全和效率,这是非泛型类和非泛型方法无法具备的。泛型通常用在集合和在集合上运行的方法中。.NET Framework 2.0 版类库提供一个新的命名空间 System.Collections.Generic,其中包含几个新的基于泛型的集合类。建议面向 2.0 版的所有应用程序都使用新的泛型集合类,而不要使用旧的非泛型集合类,如 ArrayList。有关更多信息,请参见 .NET Framework 类库中的泛型(C# 编程指南)。
当然,也可以创建自定义泛型类型和方法,以提供自己的通用解决方案,设计类型安全的高效模式。下面的代码示例演示一个用于演示用途的简单泛型链接列表类。(大多数情况下,建议使用 .NET Framework 类库提供的 List<T> 类,而不要自行创建类。)在通常使用具体类型来指示列表中所存储项的类型时,可使用类型参数 T。其使用方法如下:
· 在 AddHead 方法中作为方法参数的类型。
· 在 Node 嵌套类中作为公共方法 GetNext 和 Data 属性的返回类型。
· 在嵌套类中作为私有成员数据的类型。
注意,T 可用于 Node 嵌套类。如果使用具体类型实例化 GenericList<T>(例如,作为 GenericList<int>),则所有的 T 都将被替换为 int。
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;
// T as private member data type
private T _data;
public Node Next
{
get { return next; }
set { next = value; }
}
// T as return type of property
public T Data
{
get { return data; }
set { data = value; }
}
}
//以上是内部类Node类的内容
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> 类来创建整数列表。只需更改类型参数,即可方便地修改下面的代码示例,创建字符串或任何其他自定义类型的列表:
C#
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");
}
}
.NET Framework 中的泛型概述
本主题提供 .NET Framework 和公共语言运行库中泛型的以下功能的概述:
· 泛型类型和方法的摘要以及讨论这两者的术语。
· System.Collections.Generic 和 System.Collections.ObjectModel 命名空间中的泛型集合类。
· 其他泛型类型。
· 转换、搜索谓词以及要对数组或集合的元素进行的操作的泛型委托。
· 提供泛型类型族通用的功能的泛型接口。
什么是泛型,如何使用和定义泛型?
泛型是具有占位符(类型参数)的类、结构、接口和方法,这些占位符是类、结构、接口和方法所存储或使用的一个或多个类型的占位符。泛型集合类可以将类型参数用作它所存储的对象的类型的占位符;类型参数作为其字段的类型和其方法的参数类型出现。泛型方法可以将其类型参数用作其返回值的类型或者其形参的类型之一。下面的代码阐释一个简单的泛型类定义。
Visual Basic
Public Class Generic(Of T)
Public Field As T
End Class
C#
public class Generic<T>
{
public T Field;
}
C++
generic<typename T> public ref class Generic
{
public:
T Field;
};
在创建泛型类的实例时,会指定实际类型来替换类型参数。这会建立一个新的泛型类,称为构造泛型类,选定的类型将替换所有出现的类型参数。最后得到按照您选择的类型定制的类型安全的类,如下面的代码所示。
Visual Basic
Dim g As New Generic(Of String)
g.Field = "A string"
C#
Generic<string> g = new Generic<string>();
g.Field = "A string";
C++
Generic<String^>^ g = gcnew Generic<String^>();
g->Field = "A string";
下面的术语用于讨论 .NET Framework 中的泛型:
· “泛型类型定义”是用作模板的类、结构或接口声明,其中具有该类、结构或接口声明可以包含或使用的类型的占位符。例如,Dictionary 类可以包含两种类型:键和值。因为它只是一个模板,您不能创建作为泛型类型定义的类、结构或接口的实例。
· “泛型类型参数”或称“类型参数”是泛型类型或方法定义中的占位符。Dictionary 泛型类型具有两个类型参数:TKey 和 TValue,分别表示其键和值的类型。
· “构造泛型类型”或称“构造类型”是为泛型类型定义的泛型类型参数指定类型得到的结果。
· “泛型类型参数”是替换泛型类型参数的任何类型。
· 一般术语“泛型类型”包括构造类型和泛型类型定义。
· “约束”是加在泛型类型参数上的限制。例如,可以将类型参数限制为实现 IComparer 泛型接口的类型以确保可以对该类型的实例进行排序。还可以将类型参数限制为具有特定基类的类型、具有默认构造函数的类型或是引用类型或值类型。泛型类型的用户不能替换不满足这些约束的类型参数。
· “泛型方法定义”是具有两个参数列表的方法:一个泛型类型参数列表和一个形参列表。类型参数可以作为返回类型或形参的类型出现,如下面的代码所示。
Visual Basic
Function Generic(Of T)(ByVal arg As T) As T
Dim temp As T = arg
...
End Function
C#
T Generic<T>(T arg) { T temp = arg; ...}
C++
generic<typename T> T Generic(T arg) { T temp = arg; ...};
泛型方法可以出现在泛型或非泛型类型上。需要注意的是,并不是只要方法属于泛型类型,或者甚至是方法的形参的类型是封闭类型的泛型参数,就可以说方法是泛型方法。只有当方法具有它自己的类型参数列表时,才能称其为泛型方法。在下面的代码中,只有方法 G 是泛型方法。
C#
class A
{
T G<T>(T arg) {...}
}
class Generic<T>
{
T M(T arg) {...}
}
Visual Basic
Class A
Function G(Of T)(ByVal arg As T) As T
...
End Function
End Class
Class Generic(Of T)
Function M(ByVal arg As T) As T
...
End Function
End Class
C++
ref class A
{
generic<T> T G(T arg) {...};
};
generic<typename T> ref class Generic
{
T M(T arg) {...};
};
Visual C++、C# 和 Visual Basic 都提供了对定义和使用泛型的完全支持。有关更多信息,请参见 Visual Basic 中的泛型类型、泛型介绍(C# 编程指南)和 Overview of Generics in C++。
嵌套类型和泛型
嵌套于泛型类型中的类型依赖于封闭泛型类型的类型参数,公共语言运行库将这样的嵌套类型视为泛型,即使它们没有自己的泛型类型参数。在创建嵌套类型的实例时,需要为所有封闭泛型类型指定类型参数。
.NET Framework 中的泛型集合
在 .NET Framework 类库中,在 System.Collections.Generic 和 System.Collections.ObjectModel 命名空间中提供了很多泛型集合类。有关这些类的更多信息,请参见常用的集合类型。
System.Collections.Generic
许多泛型集合类型是非泛型类型的直接模拟。Dictionary 是 Hashtable 的泛型版本;它使用泛型结构 KeyValuePair 而不是 DictionaryEntry 进行枚举。
List 是 ArrayList 的泛型版本。存在对应于非泛型 Queue 和 Stack 类的泛型版本。
存在 SortedList 的泛型和非泛型版本,这两个版本都是介于字典和列表之间的混合类型,并且具有相似的性能特点。SortedDictionary 泛型类是提供不同性能特点的纯字典,它没有对应的非泛型类。
LinkedList 泛型类是一个真正的链接列表。它没有对应的非泛型类。
System.Collections.ObjectModel
Collection 泛型类为派生您自己的泛型集合类型提供了基类。ReadOnlyCollection 类为从实现 IList 泛型接口的任何类型生成只读集合提供了简单的方法。KeyedCollection 泛型类提供了存储包含自己键的对象的方法。
其他泛型类型











