装箱和拆箱仅针对值类型定义。 Source:
装箱是将 值类型 转换为类型对象或该值类型实现的任何接口类型的过程。当CLR装箱值类型时,它将值包装在System.Object中,并将其存储在托管堆中。取消装箱从对象中提取值类型。装箱是隐式的。拆箱是明确的。装箱和拆箱的概念是类型系统的C#统一视图的基础,在该视图中,任何类型的值都可以视为对象。
装箱和拆箱的性能很昂贵,Source:
装箱和拆箱是计算上昂贵的过程。装箱值类型时,必须创建一个全新的对象。这可能比简单的参考分配花费多达20倍的时间。取消装箱时,投射过程可能需要花费四倍的时间。
现在,如果我使用的是{em>引用类型的string
和string[]
,请执行以下操作:
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.
与值类型不同,在这里我们使用引用类型,这在计算上很昂贵。将类似装箱/拆箱的技术用于参考类型是否会对性能产生类似的影响?
它看起来类似于以下内容,但没有人谈论性能影响(如果有的话):
答案 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)
由于字符串已经是引用类型,因此不会对性能产生重大影响。