我在性能方面知道boxing and unboxing are relatively expensive。我想知道的是:
将值类型传递给方法的out
参数会导致变量的装箱/取消装箱(从而导致性能下降)吗?编译器可以优化它吗?
int number;
bool result = Int32.TryParse(value, out number);
答案 0 :(得分:18)
正如其他人所指出的,这里没有拳击。当您将变量作为对应于out或ref参数的参数传递时,您正在做的是为变量创建别名。您没有对变量的值执行任何操作。您将两个变量表示为相同的存储位置。
仅当值类型的值转换为引用类型的值时才会发生限制,并且示例中没有任何类型的转换。引用类型当然必须是System.Object,System.ValueType,System.Enum或任何接口。通常很清楚;代码中有明确或隐式的转换。但是,可能会出现不太清楚的情况。例如,当调用struct的基类型的未重写的虚方法时,就会有拳击。 (还有一些奇怪的情况,某些类型的泛型类型约束会导致意外的拳击,但它们通常不会出现在实践中。)
答案 1 :(得分: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
}
答案 2 :(得分:5)
不,没有拳击(必需/参与)。
当您执行Box变量时,对盒装实例的更改不会影响原始实例。但这正是out
应该做的事情。
编译器'以某种方式'构造对原始变量的引用。
答案 3 :(得分:1)
没有拳击; out
参数的作用是指定必须在TryParse
方法中分配该编号。无论如何,它仍然被视为int
,而不是object
。