在"out"参数中传递值类型会导致变量被装箱吗?

Jus*_*gan 14 c# performance boxing unboxing

我知道拳击和拆箱在性能方面相对昂贵.我想知道的是:

将值类型传递给方法的out参数会导致变量的装箱/取消装箱(从而导致性能下降)吗?编译器可以优化它吗?

  int number;
  bool result = Int32.TryParse(value, out number);
Run Code Online (Sandbox Code Playgroud)

Eri*_*ert 18

正如其他人所指出的那样,这里没有拳击.当您将变量作为对应于out或ref参数的参数传递时,您正在做的是为变量创建别名.你没有对变量的做任何事情.您将两个变量表示为相同的存储位置.

拳击仅在值类型的值转换为引用类型的值时发生,并且示例中没有任何类型的转换.引用类型当然必须是System.Object,System.ValueType,System.Enum或任何接口.通常很清楚; 代码中有明确或隐式的转换.但是,可能会出现不太清楚的情况.例如,当调用struct的基类型的未重写的虚方法时,就会有拳击.(还有一些奇怪的情况,某些类型的泛型类型约束会导致意外的拳击,但它们通常不会出现在实践中.)

  • @Justin:任何表现问题的最佳建议:**尝试一下,你会发现**.您可能会发现,通常通过引用传递变量与通过引用传递对引用类型的实例的引用的成本相同,这与传递IntPtr大小的值类型的成本相同.请记住,如果有可用的寄存器,则抖动可以大大优化指针大小的参数传递. (6认同)

ale*_*dej 6

没有拳击,编译器使用ldloca.s指令将对局部变量的引用推送到堆栈上(http://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.ldloca_s(VS. 71)的.aspx)

.method private hidebysig static void Func() cil managed
{
    .maxstack 2
    .locals init (
        [0] int32 num,
        [1] bool flag)
    L_0000: nop 
    L_0001: ldstr "5"
    L_0006: ldloca.s num
    L_0008: call bool [mscorlib]System.Int32::TryParse(string, int32&)
    L_000d: stloc.1 
    L_000e: ret 
}
Run Code Online (Sandbox Code Playgroud)


Hen*_*man 5

不,没有拳击(必需/参与).

当您执行Box变量时,对已装箱实例的更改不会影响原始实例.但这正是out应该做的.

编译器"以某种方式"构造对原始变量的引用.