Type.MakeGenericType(Type[]) Metode

Definisi

Mengganti elemen array jenis untuk parameter jenis definisi jenis generik saat ini dan mengembalikan objek yang Type mewakili jenis yang dibuat yang dihasilkan.

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

Parameter

typeArguments
Type[]

Array jenis yang akan digantikan untuk parameter jenis jenis generik saat ini.

Mengembalikan

Mewakili Type jenis yang dibangun yang dibentuk dengan mengganti elemen typeArguments untuk parameter jenis jenis generik saat ini.

Atribut

Pengecualian

Tipe saat ini tidak mewakili definisi tipe generik. Artinya, IsGenericTypeDefinition mengembalikan false.

typeArguments adalah null.

-atau-

Elemen apa pun adalah typeArgumentsnull.

Jumlah elemen di typeArguments tidak sama dengan jumlah parameter jenis dalam definisi jenis generik saat ini.

-atau-

Elemen apa pun dari typeArguments tidak memenuhi batasan yang ditentukan untuk parameter jenis yang sesuai dari jenis generik saat ini.

-atau-

typeArguments berisi elemen yang merupakan jenis penunjuk (IsPointer mengembalikan true), jenis by-ref (IsByRef mengembalikan true), atau Void.

Metode yang dipanggil tidak didukung di kelas dasar. Kelas turunan harus memberikan implementasi.

Contoh

Contoh berikut menggunakan MakeGenericType metode untuk membuat jenis yang dibangun dari definisi jenis generik untuk jenis tersebut Dictionary<TKey,TValue> . Jenis yang dibangun mewakili Dictionary<TKey,TValue> objek Test dengan kunci string.

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

Keterangan

Metode MakeGenericType ini memungkinkan Anda menulis kode yang menetapkan jenis tertentu ke parameter jenis definisi jenis generik, dengan demikian menciptakan objek Type yang mewakili jenis tertentu yang dikonstruksi. Anda dapat menggunakan objek ini Type untuk membuat instans runtime dari jenis yang dibangun.

Jenis yang dibangun dengan MakeGenericType dapat terbuka, artinya, beberapa argumen jenisnya dapat berupa parameter jenis dari metode atau jenis generik yang melingkupi. Anda dapat menggunakan jenis konstruksi terbuka seperti itu saat menghasilkan susunan dinamis. Misalnya, pertimbangkan kelas Base dan Derived dalam kode berikut.

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

Untuk menghasilkan Derived dalam rakitan dinamis, diperlukan untuk menyusun tipe dasarnya. Untuk melakukan ini, panggil MakeGenericType metode pada objek Type yang mewakili kelas Base, menggunakan argumen Int32 jenis generik dan parameter V jenis di Derived. Karena parameter jenis dan jenis generik keduanya diwakili oleh Type objek, array yang berisi keduanya dapat diteruskan ke MakeGenericType metode .

Note

Jenis yang dibangun seperti Base<int, V> berguna saat memancarkan kode, tetapi Anda tidak dapat memanggil MakeGenericType metode pada jenis ini karena bukan definisi jenis generik. Untuk membuat jenis konstruksi tertutup yang dapat diinstruksikan, pertama-tama panggil GetGenericTypeDefinition metode untuk mendapatkan objek yang Type mewakili definisi jenis generik lalu panggil MakeGenericType dengan argumen jenis yang diinginkan.

Objek Type yang dikembalikan oleh MakeGenericType adalah sama dengan Type yang diperoleh dengan memanggil metode GetType dari jenis yang dikonstruksi yang dihasilkan, atau metode GetType dari jenis yang dikonstruksi mana saja yang dibuat dari definisi jenis generik yang sama menggunakan argumen jenis yang sama.

Note

Array tipe generik bukanlah tipe generik. Anda tidak dapat memanggil MakeGenericType pada jenis array seperti C<T>[] (Dim ac() As C(Of T) di Visual Basic). Untuk membangun tipe generik tertutup dari C<T>[], panggil GetElementType untuk mendapatkan definisi tipe generik C<T>; panggil MakeGenericType pada definisi tipe generik untuk membuat tipe yang dibangun; dan akhirnya panggil metode MakeArrayType pada tipe yang dibangun untuk membuat tipe array. Hal yang sama berlaku untuk jenis penunjuk dan ref jenis (ByRef dalam Visual Basic).

Untuk daftar ketentuan invarian untuk istilah yang digunakan dalam refleksi generik, lihat IsGenericType keterangan properti.

Jenis berlapis

Jika jenis generik didefinisikan menggunakan C#, C++, atau Visual Basic, maka jenis berlapisnya semuanya umum. Ini berlaku bahkan jika jenis berlapis tidak memiliki parameter jenisnya sendiri, karena ketiga bahasa tersebut mencakup parameter jenis jenis yang diapit dalam daftar parameter jenis berlapis. Pertimbangkan kelas berikut:

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

Daftar parameter jenis kelas Inner berlapis memiliki dua parameter jenis, T dan U, yang pertama adalah parameter jenis kelas penutupnya. Demikian pula, daftar parameter jenis kelas Innermost1 berlapis memiliki tiga parameter jenis, T, , Udan V, dengan T dan U berasal dari kelas penutupnya. Kelas berlapis Innermost2 memiliki dua parameter jenis, T dan U, yang berasal dari kelas penutupnya.

Jika daftar parameter jenis penutup memiliki lebih dari satu parameter jenis, semua parameter jenis secara berurutan disertakan dalam daftar parameter jenis jenis jenis berlapis.

Untuk membuat jenis generik dari definisi jenis generik untuk jenis bertingkat, panggil metode MakeGenericType dengan array yang dibentuk dari penggabungan array argumen jenis dari semua jenis pembungkus, dimulai dengan jenis generik terluar, dan diakhiri dengan array argumen jenis dari jenis bertingkat itu sendiri, jika memiliki parameternya sendiri. Untuk membuat instans Innermost1, panggil MakeGenericType metode dengan array yang berisi tiga jenis, untuk ditetapkan ke T, U, dan V. Untuk membuat instans Innermost2, panggil MakeGenericType metode dengan array yang berisi dua jenis, untuk ditetapkan ke T dan U.

Bahasa menyebarluaskan parameter jenis jenis yang diapit dalam mode ini sehingga Anda dapat menggunakan parameter jenis jenis yang diapit untuk menentukan bidang jenis berlapis. Jika tidak, parameter jenis tidak akan berada dalam cakupan dalam badan jenis berlapis. Dimungkinkan untuk menentukan tipe bersarang tanpa menyebarkan parameter tipe dari tipe pembungkus, dengan menghasilkan kode dalam rakitan dinamis atau dengan menggunakan Ilasm.exe (IL Assembler). Pertimbangkan kode berikut untuk perakitan CIL:

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

Dalam contoh ini, tidak dimungkinkan untuk menentukan bidang jenis T atau U di kelas Innermost, karena parameter jenis tersebut tidak berada dalam cakupan. Kode perakit berikut mendefinisikan kelas berlapis yang bertindak seperti yang mereka lakukan jika didefinisikan dalam C++, Visual Basic, dan C#:

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

Anda dapat menggunakan Ildasm.exe (IL Disassembler) untuk memeriksa kelas berlapis yang ditentukan dalam bahasa tingkat tinggi dan mengamati skema penamaan ini.

Berlaku untuk

Lihat juga