考虑下面的 C# 代码:
使用如下:
结果(VS2015,.NET 4.5.2)如下:
附录:MeasureExecutionTime 代码可以在此处找到: https://gist.github.com/anonymous/9d60f5d09868ed3a00ec00f413f6afb0 更新:我已经在 Mono 上测试了代码,结果如下:
andrew@ubuntu-nas:/data/mono/json/x64$ mono Test.exe A: 3.40 ns/op, 294.0 mop/s B: 3.40 ns/op, 293.7 mop/s C: 6.80 ns/op, 147.1 mop/s D: 3.40 ns/op, 294.2 mop/s
可以在这里找到生成的IL代码: https://gist.github.com/anonymous/58df84eda906e83c64ce1b4fdc5497fb MS和Mono生成相同的IL代码,除了方法D。然而,这不能解释方法B的差异。如果我在没有重新编译的情况下在Mono中运行由MS生成的代码,则方法D的结果变为与B相同。
interface IFace
{
void Do();
}
class Foo: IFace
{
public void Do() { /* some action */ }
}
class Bar
{
public void A(Foo foo)
{
foo.Do();
}
public void B<T>(T foo)
where T: IFace
{
foo.Do();
}
public void C(IFace foo)
{
foo.Do();
}
public void D<T>(T foo)
where T: class, IFace
{
foo.Do();
}
}
使用如下:
Foo foo = new Foo();
Bar bar = new Bar();
MeasureExecutionTime(() => bar.A(foo), "A");
MeasureExecutionTime(() => bar.B(foo), "B");
MeasureExecutionTime(() => bar.C(foo), "C");
MeasureExecutionTime(() => bar.D(foo), "D");
结果(VS2015,.NET 4.5.2)如下:
我想知道为什么在 x86 和 x64 模式下,使用泛型方法A:3,00 ns/op,333.4 mop/s
B:5.74 ns/op,174.3 mop/s
C:5.55 ns/op,180.3 mop/s
D:5.64 ns/op,177.4 mop/s
B
完全没有优势,与使用接口相同(就像 C++ 模板 vs 虚拟调用)。甚至泛型方法比非泛型基于接口的方法稍微慢一些(当 B 和 C 测量互换时,这种效果是稳定的并且保持不变)。附录:MeasureExecutionTime 代码可以在此处找到: https://gist.github.com/anonymous/9d60f5d09868ed3a00ec00f413f6afb0 更新:我已经在 Mono 上测试了代码,结果如下:
andrew@ubuntu-nas:/data/mono/json/x64$ mono Test.exe A: 3.40 ns/op, 294.0 mop/s B: 3.40 ns/op, 293.7 mop/s C: 6.80 ns/op, 147.1 mop/s D: 3.40 ns/op, 294.2 mop/s
可以在这里找到生成的IL代码: https://gist.github.com/anonymous/58df84eda906e83c64ce1b4fdc5497fb MS和Mono生成相同的IL代码,除了方法D。然而,这不能解释方法B的差异。如果我在没有重新编译的情况下在Mono中运行由MS生成的代码,则方法D的结果变为与B相同。
IFace
类型。where T: IFace
给你什么,(IFace foo)
没有给你的呢? - MakePeaceGreatAgainT
是一个具体的类Foo
,而IFace
是一个契约。为什么CLR在运行时知道类型却不生成有效的代码呢? - Andrey NasonovT:class, IFace
约束的B,它的行为完全相同。在32位和64位的当前CLR下,在发布控制台中运行。脚本:http://pastie.org/10914172 - Marc Gravell