C#中的通用接口可以防止装箱吗? (.NET与Mono性能)

时间:2020-03-06 14:47:19  来源:igfitidea点击:

我有一个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);

}