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,必须构造基类型。 为此,请在表示类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 反汇编程序) 检查在高级语言中定义的嵌套类,并观察此命名方案。