MakeGenericType 方法允许编写向泛型类型定义的类型参数赋予特定类型的代码,从而创建表示特定构造类型的 Type 对象。可以使用此 Type 对象来创建该构造类型的运行时实例。
使用 MakeGenericType 构造的类型可以是开放的,即它们的一些类型实参可以是封闭泛型方法或类型的类型形参。您可以在发出动态程序集时使用这样的开放构造的类型。例如,考虑下面的代码中的类 Base 和 Derived。
Public Class Base(Of T, U)
End Class
Public Class Derived(Of V)
Inherits Base(Of Integer, V)
End Class
public class Base<T, U> { }
public class Derived<V> : Base<int, V> { }
generic<typename T, typename U>
public ref class Base { };
generic<typename V>
public ref class Derived : Base<int, V> { };
为了在动态程序集中生成 Derived,必须构造其基类型。为此,可以使用泛型类型实参 Int32 和 Derived 中的类型形参 V 来调用表示类 Base 的 Type 对象上的 MakeGenericType 方法。由于类型和泛型类型形参均由 Type 对象表示,因此可以向 MakeGenericType 方法传递同时包含这两者的数组。
注意 |
|---|
| 诸如 Base<int, V> 的构造类型在发出代码时非常有用,但是您不能对此类型调用 MakeGenericType 方法,因为它不是泛型类型定义。为了创建能够实例化的封闭构造的类型,可首先调用 GetGenericTypeDefinition 方法来获取表示泛型类型定义的 Type 对象,然后使用需要的类型实参调用 MakeGenericType。 |
MakeGenericType 返回的 Type 对象与调用所产生构造类型的 GetType 方法(或从使用相同类型实参的相同泛型类型定义创建的任何构造类型的 GetType 方法)获得的 Type 相同。
注意 |
|---|
| 泛型类型的数组本身不是泛型类型。您不能对诸如 C<T>[](在 Visual Basic 中为 Dim ac() As C(Of T))的数组类型调用 MakeGenericType。若要基于 C<T>[] 构造封闭泛型类型,需要调用 GetElementType 以获取泛型类型定义 C<T>,对该泛型类型定义调用 MakeGenericType 以创建构造类型,最后对该构造类型调用 MakeArrayType 方法以创建数组类型。对于指针类型和 ref 类型(在 Visual Basic 中为 ByRef)也是如此。 |
有关泛型反射中使用的术语的固定条件列表,请参见 IsGenericType 属性备注。
嵌套类型
如果泛型类型是使用 C#、C++ 或 Visual Basic 定义的,那么其嵌套类型都是泛型。即使嵌套类型没有自己的类型参数也是如此,因为所有三种语言都在嵌套类型的类型参数列表中包括了封闭类型的类型参数。请考虑下面的类:
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
public class Outermost<T>
{
public class Inner<U>
{
public class Innermost1<V> {}
public class Innermost2 {}
}
}
generic<typename T> public ref class Outermost
{
public:
generic<typename U> ref class Inner
{
public:
generic<typename V> ref class Innermost1 {};
ref class Innermost2 {};
};
};
嵌套类 Inner 的类型参数列表有两个类型参数 T 和 U,其中第一个是其封闭类的类型参数。类似地,嵌套类 Innermost1 的类型参数列表有三个类型参数 T、U 和 V,其中 T 和 U 来自其封闭类。嵌套类 Innermost2 有两个类型参数 T 和 U,它们都来自其封闭类。
如果封闭类型的参数列表有多个类型参数,则所有类型参数都按顺序包括在嵌套类型的类型参数列表中。
为了从嵌套的类型的泛型类型定义来构造泛型类型,可以使用通过串联所有封闭类型的类型实参数组(从最外层的泛型类型开始,到嵌套的类型本身的类型实参数组结束 — 如果它有自己的类型参数的话)形成的数组来调用 MakeGenericType 方法。要创建 Innermost1 的实例,可使用一个包含将分配给 T、U 和 V 的三个类型的数组来调用 MakeGenericType 方法。要创建 Innermost2 的实例,可使用一个包含将分配给 T 和 U 的两个类型的数组来调用 MakeGenericType 方法。
语言以此方式传播封闭类型的类型参数,所以,您可以使用封闭类型的类型参数来定义嵌套类型的字段。否则,类型参数将不会在嵌套类型体的范围内。通过在动态程序集中发出代码或使用 MSIL 汇编程序 (Ilasm.exe),无需传播封闭类型的类型参数即可定义嵌套类型。考虑 MSIL 汇编程序的以下代码:
.class public Outer<T> {
.class nested public Inner<U> {
.class nested public Innermost {
}
}
} 在此例中,无法在类 Innermost 中定义 T 或 U 类型的字段,因为这些类型参数不在范围内。下面的汇编程序代码定义与在 C++、Visual Basic 和 C# 中定义时具有相同表现的嵌套类:
.class public Outer<T> {
.class nested public Inner<T, U> {
.class nested public Innermost<T, U, V> {
}
}
} 可以使用 MSIL 反汇编程序 (Ildasm.exe) 检验在高级别语言中定义的嵌套类,并遵循此命名方案。