Type.MakeGenericType(Type[]) 方法

定義

用類型陣列的項目取代目前泛型類型定義的型別參數,並傳回代表所得結果建構類型的 Type 物件。Substitutes the elements of an array of types for the type parameters of the current generic type definition and returns a Type object representing the resulting constructed type.

public:
 abstract Type ^ MakeGenericType(... cli::array <Type ^> ^ typeArguments);
public:
 virtual Type ^ MakeGenericType(... cli::array <Type ^> ^ typeArguments);
public abstract Type MakeGenericType (params Type[] typeArguments);
public virtual Type MakeGenericType (params Type[] typeArguments);
abstract member MakeGenericType : Type[] -> Type
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[]

由類型組成的陣列,用來取代目前泛型類型的類型參數。An array of types to be substituted for the type parameters of the current generic type.

傳回

Type

Type,表示用 typeArguments 的項目取代目前泛型類型之類型參數所得到的建構類型。A Type representing the constructed type formed by substituting the elements of typeArguments for the type parameters of the current generic type.

例外狀況

目前類型不代表泛型型別定義。The current type does not represent a generic type definition. 亦即,IsGenericTypeDefinition 會傳回 falseThat is, IsGenericTypeDefinition returns false.

typeArgumentsnulltypeArguments is null.

-或--or- typeArguments 的項目是 nullAny element of typeArguments is null.

typeArguments 中的項目數和目前泛型型別定義的類型參數數目不同。The number of elements in typeArguments is not the same as the number of type parameters in the current generic type definition.

-或--or- typeArguments 的所有項目都不符合目前泛型型別的對應類型參數所指定的條件約束。Any element of typeArguments does not satisfy the constraints specified for the corresponding type parameter of the current generic type.

-或--or- typeArguments 中包含的項目是指標型別 (IsPointer 傳回 true)、by-ref 型別 (IsByRef 傳回 true) 或VoidtypeArguments contains an element that is a pointer type (IsPointer returns true), a by-ref type (IsByRef returns true), or Void.

基底類別不支援叫用的方法。The invoked method is not supported in the base class. 衍生類別必須提供實作。Derived classes must provide an implementation.

範例

下列範例會使用 MakeGenericType 方法,從型別的泛型型別定義建立結構化型別 Dictionary<TKey,TValue>The following example uses the MakeGenericType method to create a constructed type from the generic type definition for the Dictionary<TKey,TValue> type. 此結構型別代表 Dictionary<TKey,TValue> Test 具有字串索引鍵的物件。The constructed type represents a Dictionary<TKey,TValue> of Test objects with string keys.

using namespace System;
using namespace System::Reflection;
using namespace System::Collections::Generic;

namespace Example
{
    public ref class Test
    {
    public:
        static void CreateConstructedType(void)
        {      
            Console::WriteLine("\r\n--- Create a constructed type"
                " from the generic Dictionary`2 type.");
            
            // Create a type object representing 
            // the generic Dictionary`2 type.
            Type^ genericType = Type::GetType(
                "System.Collections.Generic.Dictionary`2");
            if (genericType != nullptr)
            {  
                DisplayTypeInfo(genericType);
            }
            else
            {
                Console::WriteLine("The type is not found");
                return;
            }
            
            // Create an array of types to substitute for the type
            // parameters of Dictionary`2. 
            // The key is of type string, and the type to be 
            // contained in the Dictionary`2 is Test.
            array<Type^>^ typeArgs = {String::typeid, Test::typeid};
            Type^ constructedType = 
                genericType->MakeGenericType(typeArgs);
            DisplayTypeInfo(constructedType);
            
            // 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^ definedType = Dictionary<String^, Test^>::typeid;
            Console::WriteLine("\tAre the constructed types "
                "equal? {0}", definedType == constructedType);
            Console::WriteLine("\tAre the generic types equal? {0}", 
                definedType->GetGenericTypeDefinition() == genericType);
        }

    private:
        static void DisplayTypeInfo(Type^ typeToDisplay)
        {   
            Console::WriteLine("\r\n{0}", typeToDisplay);
            Console::WriteLine("\tIs this a generic type definition? "
                "{0}", typeToDisplay->IsGenericTypeDefinition);
            Console::WriteLine("\tIs it a generic type? "
                "{0}", typeToDisplay->IsGenericType);
            
            array<Type^>^ typeArguments = 
                typeToDisplay->GetGenericArguments();
            Console::WriteLine("\tList type arguments ({0}):", 
                typeArguments->Length);
            
            for each (Type^ typeArgument in typeArguments)
            {   
                Console::WriteLine("\t\t{0}", typeArgument);
            }
        }
    };
}

int main(void)
{
    Example::Test::CreateConstructedType();
}

/* This example produces the following output:

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

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

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
 */
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
 */
Imports System.Reflection
Imports System.Collections.Generic

Public Class Test
    Public Shared Sub Main()
        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 代表特定結構型別的物件。The MakeGenericType method allows you to write code that assigns specific types to the type parameters of a generic type definition, thus creating a Type object that represents a particular constructed type. 您可以使用這個 Type 物件來建立所建立之型別的執行時間實例。You can use this Type object to create run-time instances of the constructed type.

以建立的型別 MakeGenericType 可以是開放式的,也就是說,某些型別引數可以是封閉式泛型方法或類型的類型參數。Types constructed with MakeGenericType can be open, that is, some of their type arguments can be type parameters of enclosing generic methods or types. 當您發出動態元件時,您可能會使用這類開啟的結構化類型。You might use such open constructed types when you emit dynamic assemblies. 例如,請考慮下列程式 Base 代碼中的類別和 DerivedFor example, consider the classes Base and Derived in the following code.

generic<typename T, typename U>
    public ref class Base { };
generic<typename V>
    public ref class Derived : Base<int, V> { };
public class Base<T, U> { }
public class Derived<V> : Base<int, V> { }
Public Class Base(Of T, U)
End Class
Public Class Derived(Of V)
    Inherits Base(Of Integer, V)
End Class

若要 Derived 在動態元件中產生,您必須建立其基底類型。To generate Derived in a dynamic assembly, it is necessary to construct its base type. 若要這樣做,請 MakeGenericType 在代表類別的物件上呼叫方法,方法是 Type Base 使用泛型型別引數 Int32 和中的型別參數 V DerivedTo do this, call the MakeGenericType method on a Type object representing the class Base, using the generic type arguments Int32 and the type parameter V from Derived. 因為類型和泛型型別參數都是由 Type 物件表示,所以包含兩者的陣列都可以傳遞給 MakeGenericType 方法。Because types and generic type parameters are both represented by Type objects, an array containing both can be passed to the MakeGenericType method.

注意

發出程式碼時,的型別(例如) Base<int, V> 很有用,但您無法 MakeGenericType 在此型別上呼叫方法,因為它不是泛型型別定義。A constructed type such as Base<int, V> is useful when emitting code, but you cannot call the MakeGenericType method on this type because it is not a generic type definition. 若要建立可具現化的封閉式結構化型別,請先呼叫 GetGenericTypeDefinition 方法來取得 Type 代表泛型型別定義的物件,然後 MakeGenericType 使用所需的型別引數呼叫。To create a closed constructed type that can be instantiated, first call the GetGenericTypeDefinition method to get a Type object representing the generic type definition and then call MakeGenericType with the desired type arguments.

Type 傳回的物件與藉 MakeGenericType Type 由呼叫所產生之 GetType 結構類型的方法,或 GetType 使用相同型別引數從相同泛型型別定義建立之任何結構化型別的方法相同。The Type object returned by MakeGenericType is the same as the Type obtained by calling the GetType method of the resulting constructed type, or the GetType method of any constructed type that was created from the same generic type definition using the same type arguments.

注意

泛型型別的陣列本身不是泛型型別。An array of generic types is not itself a generic type. 您無法 MakeGenericTypeC<T>[] Visual Basic) 中的陣列類型(例如 ()上呼叫 Dim ac() As C(Of T)You cannot call MakeGenericType on an array type such as C<T>[] (Dim ac() As C(Of T) in Visual Basic). 若要從建立封閉式泛型型別 C<T>[] ,請呼叫 GetElementType 以取得泛型型別定義, C<T> MakeGenericType 在泛型型別定義上呼叫來建立結構化的型別,最後在 MakeArrayType 結構化型別上呼叫方法來建立陣列型別。To construct a closed generic type from C<T>[], call GetElementType to obtain the generic type definition C<T>; call MakeGenericType on the generic type definition to create the constructed type; and finally call the MakeArrayType method on the constructed type to create the array type. ref Visual Basic) 中 (的指標類型和類型也是如此 ByRefThe same is true of pointer types and ref types (ByRef in Visual Basic).

如需泛型反映中所使用之規範的恆成立條件清單,請參閱 IsGenericType 屬性備註。For a list of the invariant conditions for terms used in generic reflection, see the IsGenericType property remarks.

巢狀類型Nested Types

如果使用 c #、c + + 或 Visual Basic 定義泛型型別,則其巢狀型別全都是泛型。If a generic type is defined using C#, C++, or Visual Basic, then its nested types are all generic. 即使嵌套型別沒有自己的型別參數,這種情況也是如此,因為這三種語言都包括巢狀型別之類型參數清單中的封入類型參數。This is true even if the nested types have no type parameters of their own, because all three languages include the type parameters of enclosing types in the type parameter lists of nested types. 請考慮下列類別:Consider the following classes:

generic<typename T> public ref class Outermost
{
public:
    generic<typename U> ref class Inner
    {
    public:
        generic<typename V> ref class Innermost1 {};
        ref class Innermost2 {};
    };
};
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 有兩個型別參數 TU 第一個是它的封入類別的型別參數。The type parameter list of the nested class Inner has two type parameters, T and U, the first of which is the type parameter of its enclosing class. 同樣地,嵌套類別的型別參數清單 Innermost1 有三個型別參數:、和,以及它們的封入 T U V T U 類別。Similarly, the type parameter list of the nested class Innermost1 has three type parameters, T, U, and V, with T and U coming from its enclosing classes. 此嵌套類別 Innermost2 具有兩個型別參數,以及來自其封入 T U 類別的。The nested class Innermost2 has two type parameters, T and U, which come from its enclosing classes.

如果封入類型的參數清單有一個以上的型別參數,則 order 中的所有型別參數都會包含在該巢狀型別的型別參數清單中。If the parameter list of the enclosing type has more than one type parameter, all the type parameters in order are included in the type parameter list of the nested type.

若要從嵌套型別的泛型型別定義來建立泛型型別,請將所有封入 MakeGenericType 類型的型別引數陣列(從最外層的泛型型別開始)串連在一起,並以嵌套型別本身的型別引數陣列(如果它有自己的型別參數)做為結尾,藉以使用形成的陣列來呼叫方法。To construct a generic type from the generic type definition for a nested type, call the MakeGenericType method with the array formed by concatenating the type argument arrays of all the enclosing types, beginning with the outermost generic type, and ending with the type argument array of the nested type itself, if it has type parameters of its own. 若要建立的實例 Innermost1 ,請 MakeGenericType 使用包含三種類型的陣列來呼叫方法,以指派給 T、U 和 V。若要建立的實例 Innermost2 ,請 MakeGenericType 使用包含兩種類型的陣列來呼叫方法,以指派給 T 和 U。To create an instance of Innermost1, call the MakeGenericType method with an array containing three types, to be assigned to T, U, and V. To create an instance of Innermost2, call the MakeGenericType method with an array containing two types, to be assigned to T and U.

語言會以這種方式散佈封入類型的型別參數,因此您可以使用封入類型的型別參數來定義巢狀型別的欄位。The languages propagate the type parameters of enclosing types in this fashion so you can use the type parameters of an enclosing type to define fields of nested types. 否則,型別參數不會在巢狀型別主體內的範圍內。Otherwise, the type parameters would not be in scope within the bodies of the nested types. 您可以在動態元件中發出程式碼,或使用 Ilasm.exe (IL 組合器) ,來定義巢狀型別,而不需傳播封入類型的類型參數。It is possible to define nested types without propagating the type parameters of enclosing types, by emitting code in dynamic assemblies or by using the Ilasm.exe (IL Assembler). 針對 MSIL 組合語言,請考慮下列程式碼:Consider the following code for the MSIL assembler:

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

在此範例中,無法在類別中定義型別或類別中的欄位 T U Innermost ,因為這些型別參數不在範圍內。In this example, it is not possible to define a field of type T or U in class Innermost, because those type parameters are not in scope. 下列組合器程式碼會定義以 c + +、Visual Basic 和 c # 定義的方式運作的嵌套類別:The following assembler code defines nested classes that behave the way they would if defined in C++, Visual Basic, and C#:

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

您可以使用 Ildasm.exe (IL 解譯器) 來檢查在高階語言中定義的嵌套類別,並觀察此命名配置。You can use the Ildasm.exe (IL Disassembler) to examine nested classes defined in the high-level languages and observe this naming scheme.

適用於

另請參閱