15

我知道装箱和拆箱在性能方面相对昂贵。我想知道的是:

将值类型传递给方法的out参数是否会导致变量的装箱/拆箱(从而影响性能)?编译器可以优化这个吗?

  int number;
  bool result = Int32.TryParse(value, out number);
4

4 回答 4

19

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

仅当值类型的值转换为引用类型的值时才会发生装箱,并且在您的示例中没有任何类型的转换。引用类型当然必须是 System.Object、System.ValueType、System.Enum 或任何接口。通常很清楚;代码中有显式或隐式转换。但是,可能存在不太清楚的情况。例如,当调用结构基类型的未覆盖虚拟方法时,就会出现装箱。(也有一些奇怪的情况,某些类型的泛型类型约束会导致意外的装箱,但它们通常不会在实践中出现。)

于 2011-01-26T16:56:26.360 回答
8

没有装箱,编译器使用 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 
}
于 2011-01-26T16:44:25.363 回答
6

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

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

编译器“以某种方式”构造了对原始变量的引用。

于 2011-01-26T16:32:29.477 回答
1

没有拳击;参数的out作用是指定必须在TryParse方法内分配数字。不管怎样,它仍然被视为一个int,而不是一个object

于 2011-01-26T16:34:31.380 回答