对引用类型变量进行装箱和拆箱的技术性能如何?

时间:2018-07-17 12:27:30

标签: c# .net boxing

装箱和拆箱仅针对值类型定义。 Source

  

装箱是将 值类型 转换为类型对象或该值类型实现的任何接口类型的过程。当CLR装箱值类型时,它将值包装在System.Object中,并将其存储在托管堆中。取消装箱从对象中提取值类型。装箱是隐式的。拆箱是明确的。装箱和拆箱的概念是类型系统的C#统一视图的基础,在该视图中,任何类型的值都可以视为对象。

装箱和拆箱的性能很昂贵,Source

  

装箱和拆箱是计算上昂贵的过程。装箱值类型时,必须创建一个全新的对象。这可能比简单的参考分配花费多达20倍的时间。取消装箱时,投射过程可能需要花费四倍的时间。

现在,如果我使用的是{em>引用类型的stringstring[],请执行以下操作:

string A;
return (string)(object)A;
// IMP: Here first casting is similar to boxing (though for a reference type), and second casting is similar to unboxing.

类似地,

string[] A;
return (string[])(object)A;
// IMP: Here first casting is similar to boxing (though for a reference type), and second casting is similar to unboxing.

与值类型不同,在这里我们使用引用类型,这在计算上很昂贵。将类似装箱/拆箱的技术用于参考类型是否会对性能产生类似的影响?

它看起来类似于以下内容,但没有人谈论性能影响(如果有的话):

2 个答案:

答案 0 :(得分:2)

您可能想知道C#编译器完全删除了 object强制转换 1 。最终的结果是(假设该方法从一个常量为A分配一个值,然后得到您显示的代码):

.method private hidebysig static string Thing() cil managed
{
    .maxstack 8
    L_0000: ldstr "fred"
    L_0005: castclass string
    L_000a: ret 
}

您可能会在此处对引用类型进行运行时检查,但是如果JIT由于ldstr而无法静态地证明堆栈上的引用已经被我接受,我不会感到惊讶。 string,因此可以删除它可能考虑为castclass操作生成的任何代码。

引用强制转换是断言(我知道我要处理的类型比编译器要好)。它们不像装箱和拆箱。


1 就像引用类型之间的任何 upcast 一样。

答案 1 :(得分:0)

由于字符串已经是引用类型,因此不会对性能产生重大影响。