Type.MakeGenericType(Type[]) 方法

定義

將型別陣列中的元素替換為目前通用型別定義的型別參數,並回傳 Type 一個代表所建構型別的物件。

public:
 abstract Type ^ MakeGenericType(... cli::array <Type ^> ^ typeArguments);
public:
 virtual Type ^ MakeGenericType(... cli::array <Type ^> ^ typeArguments);
public abstract Type MakeGenericType(params Type[] typeArguments);
[System.Diagnostics.CodeAnalysis.RequiresDynamicCode("The native code for this instantiation might not be available at runtime.")]
[System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("If some of the generic arguments are annotated (either with DynamicallyAccessedMembersAttribute, or generic constraints), trimming can't validate that the requirements of those annotations are met.")]
public virtual Type MakeGenericType(params Type[] typeArguments);
public virtual Type MakeGenericType(params Type[] typeArguments);
[System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("If some of the generic arguments are annotated (either with DynamicallyAccessedMembersAttribute, or generic constraints), trimming can't validate that the requirements of those annotations are met.")]
public virtual Type MakeGenericType(params Type[] typeArguments);
abstract member MakeGenericType : Type[] -> Type
[<System.Diagnostics.CodeAnalysis.RequiresDynamicCode("The native code for this instantiation might not be available at runtime.")>]
[<System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("If some of the generic arguments are annotated (either with DynamicallyAccessedMembersAttribute, or generic constraints), trimming can't validate that the requirements of those annotations are met.")>]
abstract member MakeGenericType : Type[] -> Type
override this.MakeGenericType : Type[] -> Type
abstract member MakeGenericType : Type[] -> Type
override this.MakeGenericType : Type[] -> Type
[<System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("If some of the generic arguments are annotated (either with DynamicallyAccessedMembersAttribute, or generic constraints), trimming can't validate that the requirements of those annotations are met.")>]
abstract member MakeGenericType : Type[] -> Type
override this.MakeGenericType : Type[] -> Type
Public MustOverride Function MakeGenericType (ParamArray typeArguments As Type()) As Type
Public Overridable Function MakeGenericType (ParamArray typeArguments As Type()) As Type

參數

typeArguments
Type[]

一個用來替換當前泛型型別參數的型別陣列。

傳回

A Type 代表由將 的 typeArguments 元素替換為當前泛型型別參數所構成的構造型態。

屬性

例外狀況

目前的型別並不代表一般型別定義。 也就是說,回歸 IsGenericTypeDefinitionfalse

typeArgumentsnull

-或-

任何元素 typeArguments 都是 null

元素 typeArguments 的數量與目前通用型別定義中的型別參數數不同。

-或-

任何元素 typeArguments 都不符合當前通用型別對應型別參數所規定的約束條件。

-或-

typeArguments 包含一個指標型別(IsPointer 回傳 true)、by-ref型別(IsByRef 回傳 true)、或 Void的元素。

所呼叫的方法在基類中不被支援。 衍生類別必須提供實作。

範例

以下範例使用該 MakeGenericType 方法,從該型別的通用型別定義 Dictionary<TKey,TValue> 中建立建構型態。 建構型別代表帶有字串鍵的物件。Dictionary<TKey,TValue>Test

using System;
using System.Reflection;
using System.Collections.Generic;

public class Test
{
    public static void Main()
    {
        Console.WriteLine("\r\n--- Create a constructed type from the generic Dictionary type.");

        // Create a type object representing the generic Dictionary 
        // type, by omitting the type arguments (but keeping the 
        // comma that separates them, so the compiler can infer the
        // number of type parameters).      
        Type generic = typeof(Dictionary<,>);
        DisplayTypeInfo(generic);

        // Create an array of types to substitute for the type
        // parameters of Dictionary. The key is of type string, and
        // the type to be contained in the Dictionary is Test.
        Type[] typeArgs = { typeof(string), typeof(Test) };

        // Create a Type object representing the constructed generic
        // type.
        Type constructed = generic.MakeGenericType(typeArgs);
        DisplayTypeInfo(constructed);

        // Compare the type objects obtained above to type objects
        // obtained using typeof() and GetGenericTypeDefinition().
        Console.WriteLine("\r\n--- Compare types obtained by different methods:");

        Type t = typeof(Dictionary<String, Test>);
        Console.WriteLine("\tAre the constructed types equal? {0}", t == constructed);
        Console.WriteLine("\tAre the generic types equal? {0}", 
            t.GetGenericTypeDefinition() == generic);
    }

    private static void DisplayTypeInfo(Type t)
    {
        Console.WriteLine("\r\n{0}", t);

        Console.WriteLine("\tIs this a generic type definition? {0}", 
            t.IsGenericTypeDefinition);

        Console.WriteLine("\tIs it a generic type? {0}", 
            t.IsGenericType);

        Type[] typeArguments = t.GetGenericArguments();
        Console.WriteLine("\tList type arguments ({0}):", typeArguments.Length);
        foreach (Type tParam in typeArguments)
        {
            Console.WriteLine("\t\t{0}", tParam);
        }
    }
}

/* This example produces the following output:

--- Create a constructed type from the generic Dictionary type.

System.Collections.Generic.Dictionary`2[TKey,TValue]
        Is this a generic type definition? True
        Is it a generic type? True
        List type arguments (2):
                TKey
                TValue

System.Collections.Generic.Dictionary`2[System.String, Test]
        Is this a generic type definition? False
        Is it a generic type? True
        List type arguments (2):
                System.String
                Test

--- Compare types obtained by different methods:
        Are the constructed types equal? True
        Are the generic types equal? True
 */
open System
open System.Collections.Generic

type Test() = class end

let displayTypeInfo (t: Type) =
    printfn $"\r\n{t}"

    printfn $"\tIs this a generic type definition? {t.IsGenericTypeDefinition}" 

    printfn $"\tIs it a generic type? {t.IsGenericType}"

    let typeArguments = t.GetGenericArguments()
    printfn $"\tList type arguments ({typeArguments.Length}):"
    for tParam in typeArguments do
        printfn $"\t\t{tParam}"

printfn "\r\n--- Create a constructed type from the generic Dictionary type."

// Create a type object representing the generic Dictionary 
// type, by calling .GetGenericTypeDefinition().
let generic = typeof<Dictionary<_,_>>.GetGenericTypeDefinition()
displayTypeInfo generic

// Create an array of types to substitute for the type
// parameters of Dictionary. The key is of type string, and
// the type to be contained in the Dictionary is Test.
let typeArgs = [| typeof<string>; typeof<Test> |]

// Create a Type object representing the constructed generic type.
let constructed = generic.MakeGenericType typeArgs
displayTypeInfo constructed

(* This example produces the following output:

--- Create a constructed type from the generic Dictionary type.

System.Collections.Generic.Dictionary`2[TKey,TValue]
        Is this a generic type definition? True
        Is it a generic type? True
        List type arguments (2):
                TKey
                TValue

System.Collections.Generic.Dictionary`2[System.String, Test]
        Is this a generic type definition? False
        Is it a generic type? True
        List type arguments (2):
                System.String
                Test
 *)

Public Class Test
    Public Shared Sub Main2()
        Console.WriteLine(vbCrLf & "--- Create a constructed type from the generic Dictionary type.")

        ' Create a type object representing the generic Dictionary 
        ' type, by omitting the type arguments (but keeping the 
        ' comma that separates them, so the compiler can infer the
        ' number of type parameters).
        Dim generic As Type = GetType(Dictionary(Of ,))
        DisplayTypeInfo(generic)

        ' Create an array of types to substitute for the type
        ' parameters of Dictionary. The key is of type string, and
        ' the type to be contained in the Dictionary is Test.
        Dim typeArgs() As Type = {GetType(String), GetType(Test)}

        ' Create a Type object representing the constructed generic
        ' type.
        Dim constructed As Type = generic.MakeGenericType(typeArgs)
        DisplayTypeInfo(constructed)

        ' Compare the type objects obtained above to type objects
        ' obtained using GetType() and GetGenericTypeDefinition().
        Console.WriteLine(vbCrLf & "--- Compare types obtained by different methods:")

        Dim t As Type = GetType(Dictionary(Of String, Test))
        Console.WriteLine(vbTab & "Are the constructed types equal? " _
            & (t Is constructed))
        Console.WriteLine(vbTab & "Are the generic types equal? " _
            & (t.GetGenericTypeDefinition() Is generic))
    End Sub

    Private Shared Sub DisplayTypeInfo(ByVal t As Type)
        Console.WriteLine(vbCrLf & t.ToString())

        Console.WriteLine(vbTab & "Is this a generic type definition? " _ 
            & t.IsGenericTypeDefinition)

        Console.WriteLine(vbTab & "Is it a generic type? " _ 
            & t.IsGenericType)

        Dim typeArguments() As Type = t.GetGenericArguments()
        Console.WriteLine(vbTab & "List type arguments ({0}):", _
            typeArguments.Length)
        For Each tParam As Type In typeArguments       
            Console.WriteLine(vbTab & vbTab & tParam.ToString())
        Next
    End Sub
End Class

' This example produces the following output:
'
'--- Create a constructed type from the generic Dictionary type.
'
'System.Collections.Generic.Dictionary'2[TKey,TValue]
'        Is this a generic type definition? True
'        Is it a generic type? True
'        List type arguments (2):
'                TKey
'                TValue
'
'System.Collections.Generic.Dictionary`2[System.String,Test]
'        Is this a generic type definition? False
'        Is it a generic type? True
'        List type arguments (2):
'                System.String
'                Test
'
'--- Compare types obtained by different methods:
'        Are the constructed types equal? True
'        Are the generic types equal? True

備註

MakeGenericType方法可讓您撰寫程序代碼,將特定類型指派給泛型型別定義的型別參數,從而建立Type代表特定建構型別的物件。 你可以用這個 Type 物件建立建構型別的執行時實例。

使用 MakeGenericType 建構的型別可以開啟,也就是說,其某些型別自變數可以是封入泛型方法或型別的類型參數。 當您發出動態元件時,可能會使用這類開放式建構類型。 例如,在下列程式代碼中,請考慮類別 BaseDerived

public class Base<T, U> { }
public class Derived<V> : Base<int, V> { }
type Base<'T, 'U>() = class end
type Derived<'V>() = inherit Base<int, 'V>()
Public Class Base(Of T, U)
End Class
Public Class Derived(Of V)
    Inherits Base(Of Integer, V)
End Class

若要在動態元件中產生 Derived ,必須建構其基底類型。 若要這樣做,請使用 泛型型別自變數MakeGenericType和 來自Type的型別參數Base,在代表 類別Int32的物件上V呼叫 Derived 方法。 因為型別和泛型型別參數都是由 Type 物件表示,因此包含兩者的陣列都可以傳遞至 MakeGenericType 方法。

Note

這類 Base<int, V> 建構型別在發出程序代碼時很有用,但您無法在此類型上呼叫 MakeGenericType 方法,因為它不是泛型型別定義。 若要建立可具現化的封閉建構型別,請先呼叫 GetGenericTypeDefinition 方法以取得 Type 代表泛型型別定義的 對象,然後使用所需的型別自變數呼叫 MakeGenericType

Type傳回的MakeGenericType物件與透過呼叫結果建構型別的Type方法或從使用相同型別參數在同一個泛型型別定義中創建的任何建構型別的GetType方法所取得的GetType物件相同。

Note

泛型型別的陣列本身不是泛型型別。 您無法在陣列類型上呼叫 MakeGenericType ,例如 C<T>[]Dim ac() As C(Of T) 在 Visual Basic 中)。 若要從 C<T>[]建構封閉式泛型型別,請呼叫 GetElementType 以取得泛型型別定義;在泛型型別定義 C<T>上呼叫 MakeGenericType 以建立建構型別;最後呼叫 MakeArrayType 建構型別上的 方法以建立數位類型。 指標類型和 ref 類型也是如此(ByRef 在 Visual Basic 中)。

如需泛型反映中所用詞彙的不因條件清單,請參閱 IsGenericType 屬性備註。

巢狀類型

如果使用 C#、C++或 Visual Basic 定義泛型類型,則其巢狀類型全都是泛型。 即使巢狀類型本身沒有類型參數,也是如此,因為這三種語言都會在巢狀類型的類型參數清單中包含封入型別的類型參數。 請考慮下列類別:

public class Outermost<T>
{
    public class Inner<U>
    {
        public class Innermost1<V> {}
        public class Innermost2 {}
    }
}
Public Class Outermost(Of T)
    Public Class Inner(Of U)
        Public Class Innermost1(Of V)
        End Class
        Public Class Innermost2
        End Class
    End Class
End Class

巢狀類別 Inner 的類型參數清單有兩個型別參數, T 其中 U第一個是其封入類別的類型參數。 同樣地,巢狀類別Innermost1的類型參數清單有三個類型參數、 TUV,以及 TU 來自其封入類別。 巢狀類別 Innermost2 有兩個型別參數, TU,其來自其封入類別。

如果封入類型的參數清單有多個類型參數,則所有依序的類型參數都會包含在巢狀類型的類型參數清單中。

若要從巢狀型別的泛型型別定義建構泛型型別,請呼叫 MakeGenericType 方法,方法是串連所有封入型別的類型自變數數位,從最外層泛型型別開始,並以巢狀類型本身的類型自變數數組結尾,如果它有自己的類型參數。 若要建立的實例,請使用包含三種型別的 Innermost1數位呼叫 MakeGenericType 方法,以指派給 T、U 和 V。若要建立的實例,請使用包含兩種型別的 Innermost2數位呼叫 MakeGenericType 方法,以指派給 T 和 U。

語言會以這種方式傳播封入型別的類型參數,讓您可以使用封入類型的類型參數來定義巢狀類型的欄位。 否則,類型參數將不在巢狀類型的主體範圍內,也就是說,它們在這些主體中不可用。 可以在動態元件中發出程式碼或使用 Ilasm.exe (IL 元件器),來定義巢狀類型,而不需要傳播封入型別的類型參數。 請考慮 CIL 組譯工具的下列程式代碼:

.class public Outer<T> {
    .class nested public Inner<U> {
        .class nested public Innermost {
        }
    }
}

在此範例中,無法定義 類型 TU 類別 Innermost中的欄位,因為這些類型參數不在範圍內。 下列組合語言程式碼定義了巢狀類別,這些類別的行為如同在 C++、Visual Basic 和 C# 中定義的一樣。

.class public Outer<T> {
    .class nested public Inner<T, U> {
        .class nested public Innermost<T, U, V> {
        }
    }
}

您可以使用 Ildasm.exe (IL 反組譯器) 來檢查高階語言中定義的巢狀類別,並觀察此命名配置。

適用於

另請參閱