注意:此方法在 .NET Framework 2.0 版中是新增的。
替代由当前泛型类型定义的类型参数组成的类型数组的元素,并返回表示结果构造类型的
Type 对象。
命名空间:System
程序集:mscorlib(在 mscorlib.dll 中)
Public Overridable Function MakeGenericType ( _
ParamArray typeArguments As Type() _
) As Type
Dim instance As Type
Dim typeArguments As Type()
Dim returnValue As Type
returnValue = instance.MakeGenericType(typeArguments)
public virtual Type MakeGenericType (
params Type[] typeArguments
)
public:
virtual Type^ MakeGenericType (
... array<Type^>^ typeArguments
)
public Type MakeGenericType (
Type[] typeArguments
)
public function MakeGenericType (
... typeArguments : Type[]
) : Type
参数
- typeArguments
将代替当前泛型类型的类型参数的类型数组。
返回值
typeArguments 表示的构造类型通过以下方式形成:用 Type 的元素取代当前泛型类型的类型参数。
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) 检验在高级别语言中定义的嵌套类,并遵循此命名方案。
下面的示例使用 MakeGenericType 方法基于 Dictionary 类型的泛型类型定义创建构造类型。构造类型表示具有字符串键的 Test 对象的 Dictionary。
Imports System
Imports System.Reflection
Imports System.Collections.Generic
Imports Microsoft.VisualBasic
Public Class Test
Public Shared Sub Main()
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
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
*/
using namespace System;
using namespace System::Reflection;
using namespace System::Collections::Generic;
namespace Example
{
public ref class Test
{
public:
static void CreateConstructedType(void)
{
Console::WriteLine("\r\n--- Create a constructed type"
" from the generic Dictionary`2 type.");
// Create a type object representing
// the generic Dictionary`2 type.
Type^ genericType = Type::GetType(
"System.Collections.Generic.Dictionary`2");
if (genericType != nullptr)
{
DisplayTypeInfo(genericType);
}
else
{
Console::WriteLine("The type is not found");
return;
}
// Create an array of types to substitute for the type
// parameters of Dictionary`2.
// The key is of type string, and the type to be
// contained in the Dictionary`2 is Test.
array<Type^>^ typeArgs = {String::typeid, Test::typeid};
Type^ constructedType =
genericType->MakeGenericType(typeArgs);
DisplayTypeInfo(constructedType);
// 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^ definedType = Dictionary<String^, Test^>::typeid;
Console::WriteLine("\tAre the constructed types "
"equal? {0}", definedType == constructedType);
Console::WriteLine("\tAre the generic types equal? {0}",
definedType->GetGenericTypeDefinition() == genericType);
}
private:
static void DisplayTypeInfo(Type^ typeToDisplay)
{
Console::WriteLine("\r\n{0}", typeToDisplay);
Console::WriteLine("\tIs this a generic type definition? "
"{0}", typeToDisplay->IsGenericTypeDefinition);
Console::WriteLine("\tIs it a generic type? "
"{0}", typeToDisplay->IsGenericType);
array<Type^>^ typeArguments =
typeToDisplay->GetGenericArguments();
Console::WriteLine("\tList type arguments ({0}):",
typeArguments->Length);
for each (Type^ typeArgument in typeArguments)
{
Console::WriteLine("\t\t{0}", typeArgument);
}
}
};
}
int main(void)
{
Example::Test::CreateConstructedType();
}
/* This example produces the following output:
--- Create a constructed type from the generic Dictionary`2 type.
System.Collections.Generic.Dictionary`2[KeyType,ValueType]
Is this a generic type definition? True
Is it a generic type? True
List type arguments (2):
K
V
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
*/
Windows 98、Windows 2000 SP4、Windows Millennium Edition、Windows Server 2003、Windows XP Media Center Edition、Windows XP Professional x64 Edition、Windows XP SP2、Windows XP Starter Edition
.NET Framework 并不是对每个平台的所有版本都提供支持。有关受支持版本的列表,请参见系统要求。
.NET Framework
受以下版本支持:2.0
.NET Compact Framework
受以下版本支持:2.0