C# · 12月 25, 2021

c# – 拳击,过去的事情?

这样做有什么意义吗? public static void Write<T>(T value){ textWriter.Write(value.ToString());}

……应该这样:

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

抛开明显的空取消引用可能性,如果我在哪里使用这种方法编写很多值类型,那么前者不会好得多,因为它将拥有自己的write方法来调用,或者它会臃肿二进制在生成大量额外代码方面?

这种事情的性能含义可以忽略不计,但我很好奇,它比为BCL中的每一个值类型提供重载要紧凑得多,就像BCL中的大多数编写者一样.

解决方法 从我的理解,在两种情况下拳击发生.

后者很明显,因为价值已经装箱.

前者不那么明显,但是当一个虚拟方法在一个valuetype上调用时,它需要被装箱以执行callvirt.

编辑:我刚检查了发射的IL,并且在通用情况下没有明确的装箱.虽然有东西响了.

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

编辑3:如果在值类型中未覆盖ToString(),则确实发生了拳击.

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

If thisType is a value type and
thisType does not implement method
then ptr is dereferenced,@R_950_2419@ed,and
passed as the ‘this’ pointer to the
callvirt of method

This last case can only occur when
method was defined on System.Object,
System.ValueType,or System.Enum and
not overridden by thisType. In this
last case,the @R_950_2419@ing causes a copy of
the original object to be made,
however since all methods on
System.Object,System.ValueType,and
System.Enum do not modify the state of
the object,this fact can not be
detected.

编辑4:Here is a similar question on SO.