一、简述
装箱是将值类型转换成引用类型。
拆箱是将引用类型转换成值类型,只有装箱过的对象才能拆箱。
二、装箱和拆箱的内部操作是什么样的?
.NET中,数据类型划分为值类型和引用(不等同于C++的指针)类型,与此对应,内存分配被分成了两种方式,一为栈,二为堆,注意:是托管堆。
值类型只会在栈中分配。 引用类型分配内存与托管堆。(托管堆对应于垃圾回收。)
装箱:
对值类型在堆中分配一个对象实例,并将该值复制到新的对象中。按三步进行。
1:首先从托管堆中为新生成的引用对象分配内存(大小为值类型实例大小加上一个方法表指针和一个SyncBlockIndex)。
2:然后将值类型的数据拷贝到刚刚分配的内存中。
3:返回托管堆中新分配对象的地址。这个地址就是一个指向对象的引用了。
可以看出,进行一次装箱要进行分配内存和拷贝数据这两项比较影响性能的操作。
拆箱:
1、首先获取托管堆中属于值类型那部分字段的地址,这一步是严格意义上的拆箱。
2、将引用对象中的值拷贝到位于线程堆栈上的值类型实例中。
经过这2步,可以认为是同boxing是互反操作。严格意义上的拆箱,并不影响性能,但伴随这之后的拷贝数据的操作就会同boxing操作中一样影响性能。
三、什么时候会发生装箱和拆箱
调用含有object类型的方法的时候,传入值类型的时候就会发生装箱,方法之中处理该参数的时候会发生拆箱。
定义泛型的时候,如果为了通用定义object类型,当添加值类型的时候就会发生装箱和拆箱。
四、效率影响
从原理上可以看出,装箱时,生成的是全新的引用对象,会分配托管堆的空间并且拷贝值,这会有时间损耗,也就是造成效率降低。
C# 装箱和拆箱,以及使用场景
最新推荐文章于 2024-04-22 21:15:34 发布