如果你有一个方法或类型Foo<T>
,那么 CLR 可能会为不同的 T 编译多个版本。我知道所有引用类型都共享相同的版本。它如何用于结构?对于不同的结构,代码有时是共享的还是从不共享的?例如,我可以想象所有相同大小的结构共享代码。
我很感兴趣,因为我想知道以下示例:
interface IBar
{
void DoBar();
}
struct Baz : IBar
{
public void DoBar(){ ... }
}
struct Quux : IBar
{
public void DoBar(){ ... }
}
现在,如果我执行以下操作:
public void ExecuteBar<T>(T bar) where T:IBar
{
bar.DoBar();
}
ExecuteBar(new Baz());
ExecuteBar(new Quux());
这会生成两个版本的ExecuteBar
吗? , 每个都直接(非虚拟)直接调用 Bar.DoBar()
和 Quux.DoBar()
?还是调度在运行时完成?
最佳答案
这个问题没有直接的答案,这在很大程度上取决于您使用的抖动以及泛型方法中存在什么样的代码。
起点是抖动确实为每个单独的值类型生成了不同的方法。即使对于在其他方面完全相同的结构也是如此。你可以用调试器看到的东西。使用 Debug + Windows + Disassembly 查看生成的机器码。单步进入方法,使用 Debug + Windows + Registers 窗口,EIP/RIP 寄存器显示方法在内存中的位置。
但是,像这样的泛型方法仍然有资格进行内联优化。对perf很重要,它使整个方法消失,方法中的代码被注入(inject)到调用者方法中。在这种情况下,泛型方法之间的区别确实消失了。这不是您通常可以指望接口(interface)实现方法发生的事情。但是,如果您将方法体留空,您的示例代码就会发生这种情况。 x86 和 x64 抖动的结果不同。
您只能通过查看生成的机器代码才能真正知道您得到了什么。请确保您允许优化器执行其工作,Tools + Options,Debugging,General,取消选中“Suppress JIT optimization”复选框。当然,请确保您从不依赖于此问题的准确答案。此类实现细节如有更改,恕不另行通知。
关于c# - 什么时候在 CLR 中为泛型的不同实例共享代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25610657/