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[]

要替换当前泛型类型的类型参数的类型数组。

返回

一个 Type 表示通过替换当前泛型类型的类型参数的类型参数的元素 typeArguments 而形成的构造类型。

属性

例外

当前类型不表示泛型类型定义。 也就是说, IsGenericTypeDefinition 返回 false

typeArgumentsnull

-或-

任何元素都 typeArgumentsnull.

中的 typeArguments 元素数与当前泛型类型定义中的类型参数数不同。

-或-

任何元素 typeArguments 都不符合为当前泛型类型的相应类型参数指定的约束。

-或-

typeArguments 包含一个元素,该元素是指针类型(IsPointer 返回 true)、by-ref 类型(IsByRef 返回), trueVoid

基类不支持调用的方法。 派生类必须提供实现。

示例

以下示例使用 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,必须构造基类型。 为此,请在表示类MakeGenericTypeType对象上调用Base方法,使用Int32中的泛型类型参数V和类型参数Derived。 由于类型和泛型类型参数都由 Type 对象表示,因此可以将包含这两个参数的数组传递给 MakeGenericType 该方法。

注释

构造类型(例如 Base<int, V> ,在发出代码时非常有用),但无法对此类型调用 MakeGenericType 该方法,因为它不是泛型类型定义。 若要创建可实例化的封闭构造类型,请先调用 GetGenericTypeDefinition 该方法以获取 Type 表示泛型类型定义的对象,然后使用所需的类型参数进行调用 MakeGenericType

Type返回的MakeGenericType对象与通过调用所得构造类型的Type方法获得的GetType对象相同,或者与使用相同类型参数从同一泛型类型定义创建的任何构造类型的GetType方法获得的对象相同。

注释

泛型类型的数组本身不是泛型类型。 不能调用 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 的类型参数列表有两个类型参数, TU其中第一个是其封闭类的类型参数。 同样,嵌套类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 {
        }
    }
}

在此示例中,无法定义类型 TUInnermost中的字段,因为这些类型参数不在范围内。 以下汇编程序代码定义在 C++、Visual Basic 和 C# 中定义的嵌套类的行为方式:

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

可以使用 Ildasm.exe(IL 反汇编程序) 检查在高级语言中定义的嵌套类,并观察此命名方案。

适用于

另请参阅