拳击,过去的事情?

时间:2010-08-17 05:51:37

标签: c# .net

这样做有什么意义吗?

public static void Write<T>(T value)
{
    textWriter.Write(value.ToString());
}

......应该这样:

public static void Write(object value)
{
    textWriter.Write(value.ToString());
}

抛开明显的空取消引用可能性,如果我在哪里用这种方法编写很多值类型,那么前者不会好得多,因为它将拥有它自己的write方法来调用,或者它只是根据生成的大量附加代码会使二进制文件膨胀吗?

这样的表现意味着可以忽略不计,但我很好奇,它比BCL中的每一个值类型都提供过载要紧凑得多,就像BCL中的大多数作者一样。

3 个答案:

答案 0 :(得分:7)

据我所知,在两种情况下都会发生拳击。

后者很明显,因为该值已经装箱。

前者不那么明显,但是当在一个值类型上调用虚方法时,需要将其装箱以执行callvirt

编辑:我刚检查了发出的IL,并且在通用情况下没有明确的装箱。但是有些东西响了起来。

编辑2:我可能一直在使用接口混淆自己。有明显的拳击发生。

编辑3:如果值类型中未覆盖ToString(),则会发生装箱。

我从ECMA-335第3部分第25页(仅注意到最后一个案例)得到这个:

  

如果 thisType 是值类型而且    thisType 没有实现方法   然后 ptr 被解除引用,装箱和   作为'this'指针传递给   方法的callvirt

     

最后一种情况只能发生在   方法是在System.Object上定义的,   System.ValueType,或System.Enum和   没有被 thisType 覆盖。在这   最后一种情况,拳击会导致副本   原始物体,   然而,因为所有的方法   System.ObjectSystem.ValueType和。{   System.Enum不要修改状态   对象,这个事实不可能   检测

编辑4: Here is a similar question on SO

答案 1 :(得分:1)

  • 虚拟通话可能需要装箱(如leppie已经说过的)
  • 通用在源代码中更紧凑,但在JIT代码
  • 中则不然

考虑性能:

  • 泛型在某种程度上减少了二进制大小。 JIT时间和代码位置保持不变,因为无论如何只需要过载所需的重载
  • 如果该方法不像示例中那样简单,则装箱解决方案将涉及较少的JIT调用并减少代码大小(从而也改善了局部性)。除极端情况外,这是一种难以衡量的累积效应。

要点是:对于所有情况,没有一种完美的方法。

答案 2 :(得分:1)

是的,在大多数情况下会避免拳击。我不希望在大多数情况下会产生任何显着的性能差异。正如你自己所言,这可能是微不足道的。

我认为确实在可读性方面增加了一点负担。我怀疑大多数人在尝试理解通用方法时的认知负荷比他们采用object的简单方法要多一些。谁将会使用这种方法,他们是否对泛型非常满意,以至于不会打扰他们?