装箱和拆箱(取消装箱)的概念是类型系统 C# 统一视图的基础,其中任一类型的值都被视为一个对象。
装箱
装箱是将值类型转换为 object 类型 或由此值类型实现的任何接口类型的过程。 当 CLR(公共语言运行库) 对值类型进行装箱时,会将该值包装到 System.Object 内部,再将后者存储在堆(对应于垃圾回收)上(分配并构造一个新对象);装箱是隐式的。
将整型i进行装箱并分配给object
int i = 42;
object o = i;
内存分配:
图解:对值类型在堆中分配一个新的对象实例,并将该值复制到新的对象中。按三步进行。
1:首先从堆中为新生成的引用对象分配内存(大小为值类型实例大小加上一个方法表指针和一个SyncBlockIndex)。
2:然后将值类型的数据拷贝到刚刚分配的内存中。
3:返回堆中新分配对象的地址。这个地址就是一个指向对象的引用了。
可以看出,进行一次装箱要进行分配内存和拷贝数据这两项比较影响性能的操作。
装箱操作可用于在垃圾回收堆中存储值类型
**值类型调用ToString方法不会装箱---参考链接
拆箱(取消装箱)
拆箱(取消装箱)将从对象中提取值类型。 拆箱(取消装箱)是显式的。
o=42;
int i=(int)o;
内存分配:
图解:
1、首先获取堆中属于值类型的那部分字段的地址,以确保它是给定值类型的装箱值,这一步是严格意义上的拆箱。
2、将引用对象中的值拷贝到位于栈上的值类型实例中。
经过这2步,可以认为是同装箱是互反操作。严格意义上的拆箱,并不影响性能,但伴随这之后的拷贝数据的操作就会同装箱操作中一样影响性能。
性能
相对于简单的赋值而言,装箱和取消装箱过程需要进行大量的计算。 对值类型进行装箱时,必须分配并构造一个新对象。 取消装箱所需的强制转换也需要进行大量的计算,只是程度较轻。