反映和泛用類型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 Framwork 類別庫中的泛型類型 (例如 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.

例如,如果您有代表 Type (在 Visual Basic 中為 Dictionary<int, string> ) 的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 parameterless constructor.

回到頁首Back to top

非變異值Invariants

若要了解反映中泛型類型非變異條件hapi 一般條款表,請參閱 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

標題Title 說明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.