C#中的通用接口可以防止装箱吗? (.NET与Mono性能)
我有一个C接口,其中某些方法参数声明为"对象"类型。但是,实际传递的类型可能会有所不同,具体取决于实现接口的类:
public interface IMyInterface { void MyMethod(object arg); } public class MyClass1 : IMyInterface { public void MyMethod(object arg) { MyObject obj = (MyObject) arg; // do something with obj... } } public class MyClass2 : IMyInterface { public void MyMethod(object arg) { byte[] obj = (byte[]) arg; // do something with obj... } }
MyClass2的问题在于," byte []"与" object"之间的转换是装箱和拆箱,这是计算量大的运算,会影响性能。
使用通用接口解决此问题是否可以避免装箱/拆箱?
public interface IMyInterface<T> { void MyMethod(T arg); } public class MyClass1 : IMyInterface<MyObject> { public void MyMethod(MyObject arg) { // typecast no longer necessary //MyObject obj = (MyObject) arg; // do something with arg... } } public class MyClass2 : IMyInterface<byte[]> { public void MyMethod(byte[] arg) { // typecast no longer necessary //byte[] obj = (byte[]) arg; // do something with arg... } }
在.NET与Mono中如何实现?在这两个平台上都会有任何性能影响吗?
谢谢!
解决方案
The problem with MyClass2 is that the conversion of byte[] to and from object is boxing and unboxing, which are computationally expensive operations affecting performance.
数组类型不涉及装箱,甚至值类型元素也不涉及。数组是引用类型。
(byte [])arg上的开销充其量是最小的。
我无法与Mono对话,但是使用通用接口应该可以解决MS运行时中的装箱/拆箱问题。
我不确定如何在mono中实现它,但是通用接口会有所帮助,因为编译器会为使用的每种不同类型创建特定类型的新函数(内部,在某些情况下,它可以利用相同的生成函数) 。如果生成了特定类型的函数,则无需装箱/拆箱该类型。
这就是为什么Collections.Generic库在.NET 2.0上大受好评的原因,因为集合不再需要装箱并且变得更加高效。
在Mono中,我们将获得与.NET相同的收益。
强烈建议我们一般使用Mono 1.9或者Mono 2.0 RCx,因为泛型仅支持1.9成熟。
是的,在.Net(MS不确定单声道)中,泛型是在编译时实现的,因此根本没有装箱或者拆箱操作。与Java泛型(语法糖)相反,后者只是在后台为我们执行强制转换(至少是这种方式一次)。泛型的主要问题是我们不能对通用容器进行多态处理,但这与主题有点不一样:-)
如果我们使用的是Mono的最新版本,请尽量使用2.0。
Mono与常规接口调度配合使用时,通用接口性能非常好。
在mono的所有发行版本中,通用虚拟方法[1]的派发都是可怕的,它在1.9的基础上有所改进。
问题并不那么糟糕,因为通用虚拟方法的性能问题已在计划于今年年底发布的mono(2.2)的下一个版本中得到解决。
[1]通用虚拟方法类似于:
公共接口Foo {
void Bla<T> (T a, T b);
}