反射类型和泛型类型Reflection and Generic Types

从反射的角度来说,泛型类型和普通类型之间的区别在于泛型类型具有与之关联的一组类型形参(若是泛型类型定义)或类型实参(若是构造类型)。From the point of view of reflection, the difference between a generic type and an ordinary type is that a generic type has associated with it a set of type parameters (if it is a generic type definition) or type arguments (if it is a constructed type). 泛型方法和普通方法以相同方式互不相同。A generic method differs from an ordinary method in the same way.

有两个关键点可了解反射如何处理泛型类型和方法:There are two keys to understanding how reflection handles generic types and methods:

  • 泛型类型定义和泛型方法定义的类型参数由 Type 类的实例表示。The type parameters of generic type definitions and generic method definitions are represented by instances of the Type class.

    备注

    Type 对象表示泛型类型参数时, Type 的很多属性和方法具有不同的行为。Many properties and methods of Type have different behavior when a Type object represents a generic type parameter. 这些差异记录在属性和方法主题中。These differences are documented in the property and method topics. 有关示例,请参阅 IsAutoClassDeclaringTypeFor example, see IsAutoClass and DeclaringType. 此外,某些成员仅在 Type 对象表示泛型类型参数时有效。In addition, some members are valid only when a Type object represents a generic type parameter. 有关示例,请参阅 GetGenericTypeDefinitionFor example, see GetGenericTypeDefinition.

  • 如果 Type 的实例表示泛型类型,则它包含表示类型形参(对于泛型类型定义)或类型实参(对于构造类型)的类型数组。If an instance of Type represents a generic type, then it includes an array of types that represent the type parameters (for generic type definitions) or the type arguments (for constructed types). 这同样适用于表示泛型方法的 MethodInfo 的类的实例。The same is true of an instance of the MethodInfo class that represents a generic method.

反射提供 TypeMethodInfo 的方法,它允许你访问类型形参的数组并确定 Type 的实例是表示类型形参还是表示实际类型。Reflection provides methods of Type and MethodInfo that allow you to access the array of type parameters, and to determine whether an instance of Type represents a type parameter or an actual type.

有关演示此处讨论的方法的示例代码,请参阅如何:使用反射检查和实例化泛型类型中提供的其他信息。For example code demonstrating the methods discussed here, see How to: Examine and Instantiate Generic Types with Reflection.

以下讨论假定熟悉泛型的术语,例如类型形参和实参之间的差异以及开放式或封闭式构造类型之间的差异。The following discussion assumes familiarity with the terminology of generics, such as the difference between type parameters and arguments and open or closed constructed types. 有关详细信息,请参阅泛型For more information, see Generics.

本概述包含以下几节:This overview consists of the following sections:

这是泛型类型还是泛型方法?Is This a Generic Type or Method?

当使用反射来检查未知类型(由 Type的实例表示)时,请使用 IsGenericType 属性来确定未知类型是否为泛型。When you use reflection to examine an unknown type, represented by an instance of Type, use the IsGenericType property to determine whether the unknown type is generic. 如果类型是泛型,它会返回 trueIt returns true if the type is generic. 同样,当检查未知方法(由 MethodInfo 类的实例表示)时,请使用 IsGenericMethod 属性来确定此方法是否为泛型。Similarly, when you examine an unknown method, represented by an instance of the MethodInfo class, use the IsGenericMethod property to determine whether the method is generic.

这是泛型类型定义还是泛型方法定义?Is This a Generic Type or Method Definition?

使用 IsGenericTypeDefinition 属性来确定 Type 对象是否表示泛型类型定义,并使用 IsGenericMethodDefinition 方法来确定 MethodInfo 是否表示泛型方法定义。Use the IsGenericTypeDefinition property to determine whether a Type object represents a generic type definition, and use the IsGenericMethodDefinition method to determine whether a MethodInfo represents a generic method definition.

泛型类型定义和泛型方法定义是一些从中创建可实例化类型的模板。Generic type and method definitions are the templates from which instantiable types are created. .NET Framework 类库中的泛型类型(如 Dictionary<TKey,TValue>)是泛型类型定义。Generic types in the .NET Framework class library, such as Dictionary<TKey,TValue>, are generic type definitions.

类型或方法是开放式还是封闭式的?Is the Type or Method Open or Closed?

如果可实例化类型都已替换为所有类型形参(包括所有封闭类型的所有类型形参),则泛型类型或方法是封闭式的。A generic type or method is closed if instantiable types have been substituted for all its type parameters, including all the type parameters of all enclosing types. 若为封闭式,则只能创建泛型类型的实例。You can only create an instance of a generic type if it is closed. 如果类型为开放式, Type.ContainsGenericParameters 属性将返回 trueThe Type.ContainsGenericParameters property returns true if a type is open. 对于方法, MethodBase.ContainsGenericParameters 方法执行相同的功能。For methods, the MethodBase.ContainsGenericParameters method performs the same function.

返回页首Back to top

生成封闭式泛型类型Generating Closed Generic Types

在具有泛型类型或方法定义之后,请使用 MakeGenericType 方法来创建封闭式泛型类型或者使用 MakeGenericMethod 方法来为封闭式泛型方法创建 MethodInfoOnce you have a generic type or method definition, use the MakeGenericType method to create a closed generic type or the MakeGenericMethod method to create a MethodInfo for a closed generic method.

获取泛型类型或方法定义Getting the Generic Type or Method Definition

如果你具有开放式泛型类型或方法(非泛型类型或方法定义),则不能创建它的实例,也不能提供缺少的类型形参。If you have an open generic type or method that is not a generic type or method definition, you cannot create instances of it and you cannot supply the type parameters that are missing. 必须具有泛型类型或方法定义。You must have a generic type or method definition. 使用 GetGenericTypeDefinition 方法来获取泛型类型定义或使用 GetGenericMethodDefinition 方法来获取泛型方法定义。Use the GetGenericTypeDefinition method to obtain the generic type definition or the GetGenericMethodDefinition method to obtain the generic method definition.

例如,如果你有一个表示 TypeDictionary<int, string> 对象(在 Visual Basic 中为Dictionary(Of Integer, String) )且想创建类型 Dictionary<string, MyClass>,则可以使用 GetGenericTypeDefinition 方法来获取表示 TypeDictionary<TKey, TValue> ,然后使用 MakeGenericType 方法来生成表示 TypeDictionary<int, MyClass>For example, if you have a Type object representing Dictionary<int, string> (Dictionary(Of Integer, String) in Visual Basic) and you want to create the type Dictionary<string, MyClass>, you can use the GetGenericTypeDefinition method to get a Type representing Dictionary<TKey, TValue> and then use the MakeGenericType method to produce a Type representing Dictionary<int, MyClass>.

有关非泛型类型的开放式泛型类型的示例,请参阅本主题稍后部分的“类型形参或类型实参”。For an example of an open generic type that is not a generic type, see "Type Parameter or Type Argument" later in this topic.

返回页首Back to top

检查类型实参和类型形参Examining Type Arguments and Type Parameters

使用 Type.GetGenericArguments 方法来获取 Type 对象的数组(表示泛型类型的类型形参或类型实参),并使用 MethodInfo.GetGenericArguments 方法为泛型方法执行相同的操作。Use the Type.GetGenericArguments method to obtain an array of Type objects that represent the type parameters or type arguments of a generic type, and use the MethodInfo.GetGenericArguments method to do the same for a generic method.

在了解 Type 对象表示类型形参之后,即可借助反射来回答很多其他问题。Once you know that a Type object represents a type parameter, there are many additional questions reflection can answer. 可以确定类型形参的源、位置以及约束。You can determine the type parameter's source, its position, and its constraints.

类型形参或类型实参Type Parameter or Type Argument

若要确定数组的某个特定元素是类型形参还是类型实参,请使用 IsGenericParameter 属性。To determine whether a particular element of the array is a type parameter or a type argument, use the IsGenericParameter property. 如果元素是类型形参,则 IsGenericParameter 属性为 trueThe IsGenericParameter property is true if the element is a type parameter.

在不是泛型类型定义的情况下,泛型类型也可以是开放式,此时它同时具有类型实参和类型形参。A generic type can be open without being a generic type definition, in which case it has a mixture of type arguments and type parameters. 例如,在下面的代码中,类 D 派生自通过将 D 的第一个类型参数替换为 B的第二个类型参数来创建的类型。For example, in the following code, class D derives from a type created by substituting the first type parameter of D for the second type parameter of B.

class B<T, U> {}  
class D<V, W> : B<int, V> {}  
Class B(Of T, U)  
End Class  
Class D(Of V, W)  
    Inherits B(Of Integer, V)  
End Class  
generic<typename T, typename U> ref class B {};  
generic<typename V, typename W> ref class D : B<int, V> {};  

如果你获取表示 TypeD<V, W> 对象,并使用 BaseType 属性来获取其基类型,则产生的 type B<int, V> 是开放式的,但它不是泛型类型定义。If you obtain a Type object representing D<V, W> and use the BaseType property to obtain its base type, the resulting type B<int, V> is open, but it is not a generic type definition.

泛型参数的源Source of a Generic Parameter

泛型类型形参可能来自要检查的类型、封闭类型或者泛型方法。A generic type parameter might come from the type you are examining, from an enclosing type, or from a generic method. 可以按以下方式确定泛型类型形参的源:You can determine the source of the generic type parameter as follows:

  • 首先,使用 DeclaringMethod 属性来确定类型形参是否来自泛型方法。First, use the DeclaringMethod property to determine whether the type parameter comes from a generic method. 如果属性值不是 null 引用(在 Visual Basic 中为Nothing ),则源是泛型方法。If the property value is not a null reference (Nothing in Visual Basic), then the source is a generic method.

  • 如果源不是泛型方法,则使用 DeclaringType 属性来确定泛型类型形参所属的泛型类型。If the source is not a generic method, use the DeclaringType property to determine the generic type the generic type parameter belongs to.

如果类型形参属于泛型方法,则 DeclaringType 属性返回声明泛型方法的类型,这是不相关的类型。If the type parameter belongs to a generic method, the DeclaringType property returns the type that declared the generic method, which is irrelevant.

泛型参数的位置Position of a Generic Parameter

在极少数情况下,必须确定类型形参在其声明类的类型形参列表中的位置。In rare situations, it is necessary to determine the position of a type parameter in the type parameter list of its declaring class. 例如,假设你有表示上述示例中的 Type 类型的 B<int, V> 对象。For example, suppose you have a Type object representing the B<int, V> type from the preceding example. GetGenericArguments 方法提供类型实参的列表,在检查 V 时即可使用 DeclaringMethodDeclaringType 属性来发现它的来源位置。The GetGenericArguments method gives you a list of type arguments, and when you examine V you can use the DeclaringMethod and DeclaringType properties to discover where it comes from. 然后,可以使用 GenericParameterPosition 属性来确定它在定义它的类型形参列表中的位置。You can then use the GenericParameterPosition property to determine its position in the type parameter list where it was defined. 在此示例中, V 在定义它的类型形参列表中位于位置 0(零)。In this example, V is at position 0 (zero) in the type parameter list where it was defined.

基类型和接口约束Base Type and Interface Constraints

使用 GetGenericParameterConstraints 方法来获取类型形参的基类型约束和接口约束。Use the GetGenericParameterConstraints method to obtain the base type constraint and interface constraints of a type parameter. 数组的元素顺序并不重要。The order of the elements of the array is not significant. 如果元素是接口类型,则它表示接口约束。An element represents an interface constraint if it is an interface type.

泛型参数特性Generic Parameter Attributes

GenericParameterAttributes 属性获取 GenericParameterAttributes 值,该值指示类型形参的方差(协变或逆变)和特殊约束。The GenericParameterAttributes property gets a GenericParameterAttributes value that indicates the variance (covariance or contravariance) and the special constraints of a type parameter.

协变和逆变Covariance and Contravariance

若要确定类型形参是协变还是逆变,请将 GenericParameterAttributes.VarianceMask 掩码应用到 GenericParameterAttributes 属性返回的 GenericParameterAttributes 值。To determine whether a type parameter is covariant or contravariant, apply the GenericParameterAttributes.VarianceMask mask to the GenericParameterAttributes value that is returned by the GenericParameterAttributes property. 如果结果为 GenericParameterAttributes.None,则类型形参不变。If the result is GenericParameterAttributes.None, the type parameter is invariant. 请参阅 协变和逆变See Covariance and Contravariance.

特殊约束Special Constraints

若要确定类型形参的特殊约束,请将 GenericParameterAttributes.SpecialConstraintMask 掩码应用到 GenericParameterAttributes 属性返回的 GenericParameterAttributes 值。To determine the special constraints of a type parameter, apply the GenericParameterAttributes.SpecialConstraintMask mask to the GenericParameterAttributes value that is returned by the GenericParameterAttributes property. 如果结果为 GenericParameterAttributes.None,则没有任何特殊约束。If the result is GenericParameterAttributes.None, there are no special constraints. 可将类型形参约束为引用类型、不可以为 null 的类型以及具有默认构造函数。A type parameter can be constrained to be a reference type, to be a non-nullable value type, and to have a default constructor.

返回页首Back to top

固定协定Invariants

有关泛型类型反射中常用术语的固定条件表格,请参阅 Type.IsGenericTypeFor a table of the invariant conditions for common terms in reflection for generic types, see Type.IsGenericType. 有关与泛型方法相关的其他术语,请参阅 MethodBase.IsGenericMethodFor additional terms relating to generic methods, see MethodBase.IsGenericMethod.

返回页首Back to top

TitleTitle 说明Description
如何:使用反射检查和实例化泛型类型How to: Examine and Instantiate Generic Types with Reflection 演示如何使用 TypeMethodInfo 的属性和方法来检查泛型类型。Shows how to use the properties and methods of Type and MethodInfo to examine generic types.
泛型Generics 描述泛型功能以及 .NET Framework 如何支持它。Describes the generics feature and how it is supported in the .NET Framework.
如何:使用反射发出定义泛型类型How to: Define a Generic Type with Reflection Emit 演示如何在动态程序集中使用反射发出生成泛型类型。Shows how to use reflection emit to generate generic types in dynamic assemblies.
查看类型信息Viewing Type Information 介绍 Type 类并提供演示如何使用具有各种反射类的 Type 来获取有关构造函数、方法、字段、属性和事件的信息的代码示例。Describes the Type class and provides code examples that illustrate how to use Type with various reflection classes to obtain information about constructors, methods, fields, properties, and events.