System.Type.MakeGenericType 方法

方法描述

替代由当前泛型类型定义的类型参数组成的类型数组的元素,并返回表示结果构造类型的 Type 对象。

语法定义(C# System.Type.MakeGenericType 方法 的用法)

public virtual Type MakeGenericType(
	params Type[] typeArguments
)

参数/返回值

参数值/返回值 参数类型/返回类型 参数描述/返回描述
typeArguments System-Type[] 将代替当前泛型类型的类型参数的类型数组。
返回值 System.Type Type 表示的构造类型通过以下方式形成:用 typeArguments 的元素取代当前泛型类型的类型参数。

提示和注释

MakeGenericType 方法允许编写向泛型类型定义的类型参数赋予特定类型的代码,从而创建表示特定构造类型的 Type 对象。 可以使用此 Type 对象来创建该构造类型的运行时实例。

使用 MakeGenericType 构造的类型可以是开放的,即它们的一些类型实参可以是封闭泛型方法或类型的类型形参。 您可以在发出动态程序集时使用这样的开放构造的类型。 例如,考虑下面的代码中的类 Base 和 Derived。

C#

C++

VB

复制

public class Base { }

public class Derived : Base { }

为了在动态程序集中生成 Derived,必须构造其基类型。 为此,可以使用泛型类型实参 Int32 和 Derived 中的类型形参 V 来调用表示类 Base 的 Type 对象上的 MakeGenericType 方法。 由于类型和泛型类型形参均由 Type 对象表示,因此可以向 MakeGenericType 方法传递同时包含这两者的数组。

注意

诸如 Base 的构造类型在发出代码时非常有用,但是您不能对此类型调用 MakeGenericType 方法,因为它不是泛型类型定义。 为了创建能够实例化的封闭构造的类型,可首先调用 GetGenericTypeDefinition 方法来获取表示泛型类型定义的 Type 对象,然后使用需要的类型实参调用 MakeGenericType。

MakeGenericType 返回的 Type 对象与调用所产生构造类型的 GetType 方法(或从使用相同类型实参的相同泛型类型定义创建的任何构造类型的 GetType 方法)获得的 Type 相同。

注意

泛型类型的数组本身不是泛型类型。 您不能对诸如 C[](在 Visual Basic 中为 Dim ac() As C(Of T))的数组类型调用 MakeGenericType。 若要基于 C[] 构造封闭泛型类型,需要调用 GetElementType 以获取泛型类型定义 C,对该泛型类型定义调用 MakeGenericType 以创建构造类型,最后对该构造类型调用 MakeArrayType 方法以创建数组类型。 对于指针类型和 ref 类型(在 Visual Basic 中为 ByRef)也是如此。

有关泛型反射中使用的术语的固定条件列表,请参见 IsGenericType 属性备注。

嵌套类型

如果泛型类型是使用 C#、C++ 或 Visual Basic 定义的,那么其嵌套类型都是泛型。 即使嵌套类型没有自己的类型参数也是如此,因为所有三种语言都在嵌套类型的类型参数列表中包括了封闭类型的类型参数。 请考虑下面的类:

C#

C++

VB

复制

public class Outermost

{

public class Inner

{

public class Innermost1 {}

public class Innermost2 {}

}

}

嵌套类 Inner 的类型参数列表有两个类型参数 T 和 U,其中第一个是其封闭类的类型参数。 类似地,嵌套类 Innermost1 的类型参数列表有三个类型参数 T、U 和 V,其中 T 和 U 来自其封闭类。 嵌套类 Innermost2 有两个类型参数 T 和 U,它们都来自其封闭类。

如果封闭类型的参数列表有多个类型参数,则所有类型参数都按顺序包括在嵌套类型的类型参数列表中。

为了从嵌套的类型的泛型类型定义来构造泛型类型,可以使用通过串联所有封闭类型的类型实参数组(从最外层的泛型类型开始,到嵌套的类型本身的类型实参数组结束 — 如果它有自己的类型参数的话)形成的数组来调用 MakeGenericType 方法。 若要创建 Innermost1 的实例,请对包含三个类型(这些类型要分配给 T、U 和 V)的数组调用 MakeGenericType 方法。 若要创建 Innermost2 的实例,请对包含两个类型(这些类型要分配给 T 和 U)的数组调用 MakeGenericType 方法。

语言以此方式传播封闭类型的类型参数,所以,您可以使用封闭类型的类型参数来定义嵌套类型的字段。 否则,类型参数将不会在嵌套类型体的范围内。 通过在动态程序集中发出代码或使用 Ilasm.exe(MSIL 汇编程序),无需传播封闭类型的类型参数即可定义嵌套类型。 考虑 MSIL 汇编程序的以下代码:

复制

.class public Outer {

.class nested public Inner {

.class nested public Innermost {

}

}

}

在此例中,无法在类 Innermost 中定义 T 或 U 类型的字段,因为这些类型参数不在范围内。 下面的汇编程序代码定义与在 C++、Visual Basic 和 C# 中定义时具有相同表现的嵌套类:

复制

.class public Outer {

.class nested public Inner {

.class nested public Innermost {

}

}

}

可以使用 Ildasm.exe(MSIL 反汇编程序) 检验在高级别语言中定义的嵌套类,并遵循此命名方案。

System.Type.MakeGenericType 方法例子

构造类型表示具有字符串键的 Test 对象的 Dictionary

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);
        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
 */

异常

异常 异常描述
InvalidOperationException 当前类型不表示泛型类型定义。 即,IsGenericTypeDefinition 返回 false。
ArgumentNullException
  • typeArguments 为 null。
  • typeArguments 的所有元素均为 null。
ArgumentException
  • typeArguments 中元素的个数不等于当前泛型类型定义中类型参数的个数。
  • typeArguments 的所有元素都不满足为当前泛型类型的对应类型参数指定的约束。
  • typeArguments包含元素,它是一个指针类型 (Type.IsPointer返回true),by-ref 类型 (Type.IsByRef返回true),或 Void。
NotSupportedException 基类不支持所调用的方法。 派生类必须提供实现。

命名空间

namespace: System

程序集: mscorlib(在 mscorlib.dll 中)

版本信息

.NET Framework 受以下版本支持:4、3.5、3.0、2.0 .NET Framework Client Profile 受以下版本支持:4、3.5 SP1 受以下版本支持:

适用平台

Windows 7, Windows Vista SP1 或更高版本, Windows XP SP3, Windows XP SP2 x64 Edition, Windows Server 2008(不支持服务器核心), Windows Server 2008 R2(支持 SP1 或更高版本的服务器核心), Windows Server 2003 SP2 .NET Framework 并不是对每个平台的所有版本都提供支持。有关支持的版本的列表,请参见.NET Framework 系统要求。