# .NET 中的泛型Generics in .NET

## 定义和使用泛型Defining and Using Generics

generic<typename T>
public ref class Generics
{
public:
T Field;
};

public class Generic<T>
{
public T Field;
}

Public Class Generic(Of T)
Public Field As T

End Class


static void Main()
{
Generics<String^>^ g = gcnew Generics<String^>();
g->Field = "A string";
//...
Console::WriteLine("Generics.Field           = \"{0}\"", g->Field);
Console::WriteLine("Generics.Field.GetType() = {0}", g->Field->GetType()->FullName);
}

public static void Main()
{
Generic<string> g = new Generic<string>();
g.Field = "A string";
//...
Console.WriteLine("Generic.Field           = \"{0}\"", g.Field);
Console.WriteLine("Generic.Field.GetType() = {0}", g.Field.GetType().FullName);
}

Public Shared Sub Main()
Dim g As New Generic(Of String)
g.Field = "A string"
'...
Console.WriteLine("Generic.Field           = ""{0}""", g.Field)
Console.WriteLine("Generic.Field.GetType() = {0}", g.Field.GetType().FullName)
End Sub


### 泛型术语Generics terminology

• 泛型类型定义 是用作模板的类、结构或接口声明，带有可包含或使用的类型的占位符。A generic type definition is a class, structure, or interface declaration that functions as a template, with placeholders for the types that it can contain or use. 例如， System.Collections.Generic.Dictionary<TKey,TValue> 类可以包含两种类型：密钥和值。For example, the System.Collections.Generic.Dictionary<TKey,TValue> class can contain two types: keys and values. 由于泛型类型定义只是一个模板，所以你无法创建作为泛型类型定义的类、结构或接口的实例。Because a generic type definition is only a template, you cannot create instances of a class, structure, or interface that is a generic type definition.

• 泛型类型参数（或类型参数）是泛型类型或方法定义中的占位符。Generic type parameters, or type parameters, are the placeholders in a generic type or method definition. System.Collections.Generic.Dictionary<TKey,TValue> 泛型类型具有两个类型形参 TKeyTValue，它们分别代表密钥和值的类型。The System.Collections.Generic.Dictionary<TKey,TValue> generic type has two type parameters, TKey and TValue, that represent the types of its keys and values.

• 构造泛型类型（或 构造类型）是为泛型类型定义的泛型类型形参指定类型的结果。A constructed generic type, or constructed type, is the result of specifying types for the generic type parameters of a generic type definition.

• 泛型类型实参 是被泛型类型形参所替代的任何类型。A generic type argument is any type that is substituted for a generic type parameter.

• 一般术语 泛型类型 包括构造类型和泛型类型定义。The general term generic type includes both constructed types and generic type definitions.

• 借助泛型类型参数的协变逆变，可以使用类型自变量的派生程度比目标构造类型更高（协变）或更低（逆变）的构造泛型类型。Covariance and contravariance of generic type parameters enable you to use constructed generic types whose type arguments are more derived (covariance) or less derived (contravariance) than a target constructed type. 协变和逆变统称为“变体” 。Covariance and contravariance are collectively referred to as variance. 有关详细信息，请参阅协变和逆变For more information, see Covariance and Contravariance.

• 约束是对泛型类型参数的限制。Constraints are limits placed on generic type parameters. 例如，你可能会将一个类型形参限制为实现 System.Collections.Generic.IComparer<T> 泛型接口的类型，以确保可对该类型的实例进行排序。For example, you might limit a type parameter to types that implement the System.Collections.Generic.IComparer<T> generic interface, to ensure that instances of the type can be ordered. 此外，你还可以将类型形参限制为具有特定基类、具有无参数构造函数或作为引用类型或值类型的类型。You can also constrain type parameters to types that have a particular base class, that have a parameterless constructor, or that are reference types or value types. 泛型类型的用户不能替换不满足约束条件的类型实参。Users of the generic type cannot substitute type arguments that do not satisfy the constraints.

• 泛型方法定义 是具有两个形参列表的方法：泛型类型形参列表和形参列表。A generic method definition is a method with two parameter lists: a list of generic type parameters and a list of formal parameters. 类型形参可作为返回类型或形参类型出现，如以下代码所示。Type parameters can appear as the return type or as the types of the formal parameters, as the following code shows.

generic<typename T>
T Generic(T arg)
{
T temp = arg;
//...
return temp;
}

T Generic<T>(T arg)
{
T temp = arg;
//...
return temp;
}

Function Generic(Of T)(ByVal arg As T) As T
Dim temp As T = arg
'...
Return temp
End Function


ref class A
{
generic<typename T>
T G(T arg)
{
T temp = arg;
//...
return temp;
}
};
generic<typename T>
ref class Generic
{
T M(T arg)
{
T temp = arg;
//...
return temp;
}
};

class A
{
T G<T>(T arg)
{
T temp = arg;
//...
return temp;
}
}
class Generic<T>
{
T M(T arg)
{
T temp = arg;
//...
return temp;
}
}

Class A
Function G(Of T)(ByVal arg As T) As T
Dim temp As T = arg
'...
Return temp
End Function
End Class
Class Generic(Of T)
Function M(ByVal arg As T) As T
Dim temp As T = arg
'...
Return temp
End Function
End Class


• 类型安全。Type safety. 泛型将类型安全的负担从你那里转移到编译器。Generics shift the burden of type safety from you to the compiler. 没有必要编写代码来测试正确的数据类型，因为它会在编译时强制执行。There is no need to write code to test for the correct data type because it is enforced at compile time. 降低了强制类型转换的必要性和运行时错误的可能性。The need for type casting and the possibility of run-time errors are reduced.

• 代码更少且可以更轻松地重用代码。Less code and code is more easily reused. 无需从基类型继承，无需重写成员。There is no need to inherit from a base type and override members. 例如，可立即使用 LinkedList<T>For example, the LinkedList<T> is ready for immediate use. 例如，你可以使用下列变量声明来创建字符串的链接列表：For example, you can create a linked list of strings with the following variable declaration:

LinkedList<String^>^ llist = gcnew LinkedList<String^>();

LinkedList<string> llist = new LinkedList<string>();

Dim llist As New LinkedList(Of String)()

• 性能更好。Better performance. 泛型集合类型通常能更好地存储和操作值类型，因为无需对值类型进行装箱。Generic collection types generally perform better for storing and manipulating value types because there is no need to box the value types.

• 泛型委托可以在无需创建多个委托类的情况下进行类型安全的回调。Generic delegates enable type-safe callbacks without the need to create multiple delegate classes. 例如， Predicate<T> 泛型委托允许你创建一种为特定类型实现你自己的搜索标准的方法并将你的方法与 Array 类型比如 FindFindLastFindAll方法一起使用。For example, the Predicate<T> generic delegate allows you to create a method that implements your own search criteria for a particular type and to use your method with methods of the Array type such as Find, FindLast, and FindAll.

• 泛型简化动态生成的代码。Generics streamline dynamically generated code. 使用具有动态生成的代码的泛型时，无需生成类型。When you use generics with dynamically generated code you do not need to generate the type. 这会增加方案数量，在这些方案中你可以使用轻量动态方法而非生成整个程序集。This increases the number of scenarios in which you can use lightweight dynamic methods instead of generating entire assemblies. 有关详细信息，请参阅如何：定义和执行动态方法 DynamicMethodFor more information, see How to: Define and Execute Dynamic Methods and DynamicMethod.

• 泛型类型可从多数基类中派生，如 MarshalByRefObject （约束可用于要求泛型类型形参派生自诸如 MarshalByRefObject的基类）。Generic types can be derived from most base classes, such as MarshalByRefObject (and constraints can be used to require that generic type parameters derive from base classes like MarshalByRefObject). 不过，.NET Framework 不支持上下文绑定泛型类型。However, the .NET Framework does not support context-bound generic types. 泛型类型可派生自 ContextBoundObject，但尝试创建该类型实例会导致 TypeLoadExceptionA generic type can be derived from ContextBoundObject, but trying to create an instance of that type causes a TypeLoadException.

• 枚举不能具有泛型类型形参。Enumerations cannot have generic type parameters. 枚举偶尔可为泛型（例如，因为它嵌套在被定义使用 Visual Basic、C# 或 C++ 的泛型类型中）。An enumeration can be generic only incidentally (for example, because it is nested in a generic type that is defined using Visual Basic, C#, or C++). 有关详细信息，请参阅 Common Type System中的“枚举”。For more information, see "Enumerations" in Common Type System.

• 轻量动态方法不能是泛型。Lightweight dynamic methods cannot be generic.

• 在 Visual Basic、C# 和 C++ 中，包含在泛型类型中的嵌套类型不能被实例化，除非已将类型分配给所有封闭类型的类型形参。In Visual Basic, C#, and C++, a nested type that is enclosed in a generic type cannot be instantiated unless types have been assigned to the type parameters of all enclosing types. 另一种说法是：在反射中，定义使用这些语言的嵌套类型包括其所有封闭类型的类型形参。Another way of saying this is that in reflection, a nested type that is defined using these languages includes the type parameters of all its enclosing types. 这使封闭类型的类型形参可在嵌套类型的成员定义中使用。This allows the type parameters of enclosing types to be used in the member definitions of a nested type. 有关详细信息，请参阅 MakeGenericType中的“嵌套类型”。For more information, see "Nested Types" in MakeGenericType.

备注

通过在动态程序集中触发代码或通过使用 Ilasm.exe (IL Assembler) 定义的嵌套类型不需要包括其封闭类型的类型参数；然而，如果不包括，类型参数就不会在嵌套类的范围内。A nested type that is defined by emitting code in a dynamic assembly or by using the Ilasm.exe (IL Assembler) is not required to include the type parameters of its enclosing types; however, if it does not include them, the type parameters are not in scope in the nested class.

## 类库和语言支持Class Library and Language Support

.NET 在以下命名空间中提供了大量泛型集合类：.NET provides a number of generic collection classes in the following namespaces:

System 命名空间提供实现排序和等同性比较的泛型接口，还提供事件处理程序、转换和搜索谓词的泛型委托类型。Generic interfaces for implementing sort and equality comparisons are provided in the System namespace, along with generic delegate types for event handlers, conversions, and search predicates.

Visual C++、C# 和 Visual Basic 都对定义和使用泛型提供完全支持。Visual C++, C#, and Visual Basic all provide full support for defining and using generics. 有关语言支持的详细信息，请参阅 Visual Basic 中的泛型类型泛型简介Visual C++ 中的泛型概述For more information about language support, see Generic Types in Visual Basic, Introduction to Generics, and Overview of Generics in Visual C++.

## 嵌套类型和泛型Nested Types and Generics

TitleTitle 说明Description
.NET 中的泛型集合Generic Collections in .NET 介绍了 .NET 中的泛型集合类和其他泛型类型。Describes generic collection classes and other generic types in .NET.

Visual Basic 中的泛型类型Generic Types in Visual Basic 为 Visual Basic 用户描述泛型功能，包括有关使用和定义泛型类型的帮助主题。Describes the generics feature for Visual Basic users, including how-to topics for using and defining generic types.

Visual C++ 中的泛型概述Overview of Generics in Visual C++ 为 C++ 用户描述泛型功能，包括泛型和模板之间的差异。Describes the generics feature for C++ users, including the differences between generics and templates.

## 参考Reference

System.Collections.Generic

System.Collections.ObjectModel

System.Reflection.Emit.OpCodes