理解“装箱”和“拆箱”
值类型变量在线程堆栈上分配存储空间,然而由于其派生自object类,按照面向对象编程的多态原则,我们可以用一个object类变量存放一个值类型数据。
如:int num=123; object obj=num;
很明显,第2句代码将值类型的数据”123“放到了一个Object 类型的变量obj中,而Object是一个引用类型的变量,其引用的对象必须存活于托管堆中。为了解决这个问题,CLR将值类型的数据”包裹“到一个匿名的托管对象内,并将此托管对象的引用放到Object类型的变量obj中,这个过程称为”装箱“,装箱后对象的内存布局如下图:
需要注意的是,变量num与变量obj是两个完全独立的变量,知识初值相同罢了,对其中任何一个变量值的改变不会另一个。
int num=123;
object obj=i //装箱
int value=(int) obj; //拆箱
此处代码装箱后的数据再”拆箱“,将其值赋给变量value 如图:
装箱与拆箱对程序性能的影响
”装箱“ 与“拆箱”使我们可以把值类型变量看成是引用类型的变量,但这个操作时好事的,会影响程序的运行性能,因此应该尽量避免在程序中使用装箱与拆箱操作。
static long SumWithBox()
{
object sum=0; //装箱
for(long i=0;i<10000000;i++)
sum=(long)sum+i; //先拆箱,求和,再装箱
return (long)sum; //拆箱
}
此方法在计算机上运行时,与直接使用long局部变量而无需装箱/拆箱操作的对应版本相比,运行速度不到后者的三分之一。