C# 中的泛型接口是否防止装箱?(.NET vs Mono performance)

本文关键字:NET vs Mono performance 泛型接口 是否 | 更新日期: 2023-09-27 17:47:21

我有一个 C# 接口,其中某些方法参数声明为 object 类型。但是,传递的实际类型可能会有所不同,具体取决于实现接口的类:

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中实现的?是否会对任一平台产生任何性能影响?

谢谢!

C# 中的泛型接口是否防止装箱?(.NET vs Mono performance)

你将在 Mono 中获得与在 .NET 中相同的好处。

我们强烈建议您一般使用 Mono 1.9 或 Mono 2.0 RCx,因为泛型支持仅在 1.9 中成熟。

MyClass2 的问题在于 字节 [] 与 对象是装箱和拆箱,其中 计算成本高 影响性能的操作。

数组类型不涉及装箱,即使是值类型元素也不涉及装箱。数组是一种引用类型。

(byte[]) arg 上的开销充其量是最小的。

我不确定它是如何在单声道中实现的,但通用接口会有所帮助,因为编译器为所使用的每种不同类型的新函数创建一个特定类型的新函数(在内部,在某些情况下它可以使用相同的生成函数)。 如果生成了特定类型的函数,则无需对该类型进行装箱/取消装箱。

这就是为什么 Collections.Generic 库在 .NET 2.0 上大受欢迎,因为集合不再需要装箱,并且效率大大提高。

是的,在 .Net 中(MS 不确定单声道)泛型是在编译时实现的,因此根本没有装箱或取消装箱。 与java泛型相反,java泛型是语法糖,只是在后台为你执行强制转换(至少曾经是这样)。 泛型的主要问题是你不能多态地处理泛型容器,但这有点偏离你的主题:-)

我不能和 Mono 说话,但使用通用接口应该可以解决 MS 运行时中的装箱/拆箱问题。

鉴于您使用的是最新版本的单声道,如果可以的话,请使用 2.0。

Mono 上的通用接口性能非常好,与常规接口调度配对。

在所有发布的单声道版本上,通用虚拟方法[1]的调度都很糟糕,它在 1.9 中有所改进。

这个问题并没有那么糟糕,因为通用虚拟方法的性能问题已经在计划于今年年底发布的单声道(2.2)的下一个版本中得到了修复。

[1] 泛型虚拟方法如下所示:

公共接口 Foo {

  void Bla<T> (T a, T b);

}