System.Type.MakeGenericType 方法

本文提供了此 API 参考文档的补充说明。

此方法 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 ,必须构造其基类型。 为此,请使用泛型类型参数和类型参数Int32VDerived中对表示类Base的对象调用MakeGenericType该方法Type。 由于类型和泛型类型参数都由 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的类型参数列表具有三个类型参数,UT以及包含VTU来自其封闭类。 嵌套类 Innermost2 具有两个类型参数, T 这些 U参数来自其封闭类。

如果封闭类型的参数列表具有多个类型参数,则嵌套类型的类型参数列表中包括所有类型参数。

若要从嵌套类型的泛型类型定义构造泛型类型,请通过连接所有封闭类型的类型参数数组(以最外部泛型类型开头)并用嵌套类型本身的类型自变量数组结束(如果数组具有自己的类型参数)来调用 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 反汇编程序) 检查在高级语言中定义的嵌套类,并观察此命名方案。