typeof运算符如何在泛型方法中获取类型参数?

时间:2019-02-10 05:46:41

标签: c#

在Java中,此代码不起作用:

public <T> void foo() { print(T.class); } // compile time error

因为通用类型T在运行时被删除。要使用T,我必须将其用作参数,这会将String.class推入堆栈

public <T> void foo(Class<T> T) { print(T); }
public void bar() { foo(String.class); }

但是在C#中,我可以在运行时获取类型参数:

public void Foo<T>() { print(typeof(T)); }

它如何工作?编译器(或vm)是否自动将void Foo<T>()转换为void Foo(Type T)


更新:

我反汇编了字节码,并得到了类似的内容:

ldtoken    !!T
call       System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)

由于ldtoken是一条“将元数据令牌转换为其运行时表示形式的指令”,因此很明显T的运行时类型将存储为元数据。

我猜每个方法都有它自己的“元数据表”(或类似的东西),因此调用Foo<string>()Foo<object>()将生成两个“方法句柄”和两个“元数据表”,但是共享相同的机器代码。是吗?

2 个答案:

答案 0 :(得分:4)

  

编译器(或vm)会自动将void Foo()转换为void Foo(Type T)吗?

不,不是。泛型方法的主体是在运行时动态生成的。因此,例如,当您提供T作为int时,将生成此方法:

public void Foo<int>() { print(typeof(int)); }

每次您传递不同的类型都会发生这种情况。但是,如果再次使用同一类型,则CLR将缓存先前生成的方法并执行它,而不是生成新的方法。

答案 1 :(得分:0)

在.NET中,不会删除泛型。 CLR从头到尾都实现了泛型。

相关问题