共用方式為


反射和泛型型別

從反映的觀點來看,泛型型別與一般型別之間的差異在於泛型型別與一組類型參數相關聯(如果是泛型型別定義)或類型自變數(如果是建構型別)。 泛型方法與一般方法不同,方式相同。

瞭解反映如何處理泛型類型和方法有兩個索引鍵:

  • 泛型型別定義和泛型方法定義的型別參數是由 類別的 Type 實例表示。

    備註

    當物件代表泛型型別參數時Type,的許多Type屬性和方法都有不同的行為。 這些差異記載於 屬性和方法文章中。 例如,請參閱 IsAutoClassDeclaringType。 此外,某些成員只有在物件代表泛型類型參數時才 Type 有效。 如需範例,請參閱 GetGenericTypeDefinition

  • 如果的 Type 實例代表泛型型別,則會包含型別數位,這些型別代表型別參數(適用於泛型型別定義)或型別自變數(適用於建構型別)。 代表泛型方法之 MethodInfo 類別的實例也是如此。

反映提供 和 Type 的方法MethodInfo,可讓您存取型別參數的陣列,以及判斷的Type實例是否代表類型參數或實際類型。

如需示範此處所討論方法的範例程式代碼,請參閱 如何:使用反映檢查和具現化泛型類型

下列討論假設熟悉泛型的術語,例如類型參數和自變數之間的差異,以及開啟或封閉式建構類型。 如需詳細資訊,請參閱 泛型

這是泛型類型或方法嗎?

當您使用反映來檢查由 實例表示的 Type未知類型時,請使用 IsGenericType 屬性來判斷未知類型是否為泛型。 如果類型為泛型,則會傳 true 回 。 同樣地,當您檢查由 類別實例表示的 MethodInfo 未知方法時,請使用 IsGenericMethod 屬性來判斷方法是否為泛型。

這是泛型類型或方法定義嗎?

IsGenericTypeDefinition使用 屬性來判斷物件是否Type代表泛型型別定義,並使用 IsGenericMethodDefinition 方法來判斷 是否MethodInfo代表泛型方法定義。

泛型類型和方法定義是建立可具現化類型的範本。 .NET 連結庫中的泛型型別,例如 Dictionary<TKey,TValue>, 是泛型型別定義。

類型或方法是否開啟或關閉?

如果具現化類型已取代其所有型別參數,包括所有封入型別的所有類型參數,則泛型型別或方法會關閉。 只有在關閉泛型類型時,您才能建立泛型類型的實例。 如果類型已開啟,則 Type.ContainsGenericParameters 屬性會傳 true 回 。 對於方法, MethodBase.ContainsGenericParameters 方法會執行相同的函式。

產生封閉式泛型類型

一旦您有泛型型別或方法定義,請使用 MakeGenericType 方法來建立封閉式泛型型別或 MakeGenericMethod 方法,為封閉式泛型方法建立 MethodInfo

取得泛型類型或方法定義

如果您有不是泛型型別或方法定義的開放式泛型型別或方法,則無法建立它的實例,而且無法提供遺漏的類型參數。 您必須具有泛型類型或方法定義。 GetGenericTypeDefinition使用 方法來取得泛型型別定義或 GetGenericMethodDefinition 方法,以取得泛型方法定義。

例如,如果您有代表 TypeDictionary<int, string> 的物件,而且想要建立型 Dictionary<string, MyClass>別,您可以使用 GetGenericTypeDefinition 方法取得 Type 表示 Dictionary<TKey, TValue> ,然後使用 MakeGenericType 方法產生 Type 代表 Dictionary<int, MyClass>的 。

如需非泛型型別之開放式泛型類型的範例,請參閱 Type 參數或類型自變數

檢查類型自變數和類型參數

Type.GetGenericArguments使用 方法可取得物件數位Type,這些物件代表泛型型別的類型參數或型別自變數,並使用 MethodInfo.GetGenericArguments 方法對泛型方法執行相同的動作。

一旦您知道 Type 物件代表類型參數,就有許多其他問題反映可以回答。 您可以判斷類型參數的來源、其位置和條件約束。

類型參數或類型自變數

若要判斷陣列的特定專案是類型參數還是類型自變數,請使用 IsGenericParameter 屬性。 如果項目是類型參數,則 IsGenericParameter 屬性 true 為 。

泛型型別可以開啟而不做泛型型別定義,在此情況下,它混合了型別自變數和型別參數。 例如,在下列程式代碼中,類別D衍生自 型別,其方法是取代 的第二個型別參數的第一個型別參數DB

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

如果您取得Type代表 的物件並使用 D<V, W> 屬性來取得其基底類型,則結果BaseType會開啟,但不是泛型type B<int, V>型別定義。

泛型參數的來源

泛型型別參數可能來自您要檢查的類型、封入類型或泛型方法。 您可以判斷泛型型別參數的來源,如下所示:

  • 首先,使用 DeclaringMethod 屬性來判斷類型參數是否來自泛型方法。 如果屬性值不是 Null 參考,則來源是泛型方法。
  • 如果來源不是泛型方法,請使用 DeclaringType 屬性來判斷泛型型別參數所屬的泛型型別。

如果類型參數屬於泛型方法,則 DeclaringType 屬性會傳回宣告泛型方法的類型,這無關緊要。

泛型參數的位置

在罕見的情況下,必須判斷類型參數在其宣告類別的類型參數清單中的位置。 例如,假設您有物件 Type ,代表 B<int, V> 上述範例中的型別。 方法 GetGenericArguments 會提供類型自變數的清單,當您檢查 V 時,可以使用 DeclaringMethodDeclaringType 屬性來探索其來源。 然後 GenericParameterPosition ,您可以使用 屬性來判斷其在定義所在類型參數清單中的位置。 在此範例中, V 位於已定義類型參數清單中的位置 0 (零)。

基底類型和介面條件約束

GetGenericParameterConstraints使用方法來取得型別參數的基底類型條件約束和介面條件約束。 陣列元素的順序並不重要。 如果專案是介面類型,則表示介面條件約束。

泛型參數屬性

屬性 GenericParameterAttributes 會取得 GenericParameterAttributes 值,指出變異數(共變數或反變數)和類型參數的特殊條件約束。

共變性和逆變性

若要判斷類型參數為covariant或contravariant,請將 GenericParameterAttributes.VarianceMask 遮罩套用至 GenericParameterAttributes 屬性所 GenericParameterAttributes 傳回的值。 如果結果為 GenericParameterAttributes.None,則類型參數是不變的。 如需詳細資訊,請參閱 共變數和反變數

特殊條件約束

若要判斷類型參數的特殊條件約束,請將 GenericParameterAttributes.SpecialConstraintMask 遮罩套用至 GenericParameterAttributes 屬性所 GenericParameterAttributes 傳回的值。 如果結果為 GenericParameterAttributes.None,則沒有任何特殊條件約束。 型別參數可以限制為參考型別、不可為 Null 的實值型別,以及具有無參數建構函式。

不因變數

如需泛型型別反映中常見詞彙的不因條件表格,請參閱 Type.IsGenericType。 如需與泛型方法相關的其他詞彙,請參閱 MethodBase.IsGenericMethod