我知道装箱和拆箱在性能方面相对昂贵。我想知道的是:
将值类型传递给方法的out
参数是否会导致变量的装箱/拆箱(从而影响性能)?编译器可以优化这个吗?
int number;
bool result = Int32.TryParse(value, out number);
我知道装箱和拆箱在性能方面相对昂贵。我想知道的是:
将值类型传递给方法的out
参数是否会导致变量的装箱/拆箱(从而影响性能)?编译器可以优化这个吗?
int number;
bool result = Int32.TryParse(value, out number);
正如其他人指出的那样,这里没有拳击。当您将变量作为与 out 或 ref 参数对应的参数传递时,您所做的是为变量创建别名。您没有对变量的值做任何事情。您正在使两个变量代表相同的存储位置。
仅当值类型的值转换为引用类型的值时才会发生装箱,并且在您的示例中没有任何类型的转换。引用类型当然必须是 System.Object、System.ValueType、System.Enum 或任何接口。通常很清楚;代码中有显式或隐式转换。但是,可能存在不太清楚的情况。例如,当调用结构基类型的未覆盖虚拟方法时,就会出现装箱。(也有一些奇怪的情况,某些类型的泛型类型约束会导致意外的装箱,但它们通常不会在实践中出现。)
没有装箱,编译器使用 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
}
不,没有拳击(必需/参与)。
当您对变量进行装箱时,对装箱实例的更改不会影响原始实例。但这正是out
应该做的。
编译器“以某种方式”构造了对原始变量的引用。
没有拳击;参数的out
作用是指定必须在TryParse
方法内分配数字。不管怎样,它仍然被视为一个int
,而不是一个object
。