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

C# `typeof`运算符如何在泛型方法中获取类型参数?,c#,C#,在Java中,此代码不起作用: public <T> void foo() { print(T.class); } // compile time error 但在C#中,我可以在运行时获取类型参数: public void Foo<T>() { print(typeof(T)); } 由于ldtoken是一条“将元数据令牌转换为其运行时表示形式”的指令,因此T的运行时类型显然存储为元数据 我猜每个方法都有自己的“元数据表”(或者类似的东西),因此调用Foo()和F

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

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

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

public void Foo<T>() { print(typeof(T)); }
由于
ldtoken
是一条“将元数据令牌转换为其运行时表示形式”的指令,因此
T
的运行时类型显然存储为元数据


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

在.NET中,泛型不会被删除。CLR实现泛型,一直到字节码

编译器(或vm)是否自动将void Foo()转换为void Foo(类型T)

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

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

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

您的最后一点不太正确。CLR为每个值类型生成新的运行时方法,但对所有引用类型只生成一个。解释说。。。(您可能已经在研究中看到过)Java在运行时强制使用泛型类型系统,而运行时不知道泛型。C#的情况并非如此。在C#中,运行时和语言都是为了支持泛型而编写的。
ldtoken    !!T
call       System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)
public void Foo<int>() { print(typeof(int)); }