- 通过ILDasm查看IL代码来了解一下,在装箱过程中所执行的操作
.locals init ([0] object obj) //声明类型为object的变量obj,索引值为0
IL_0000: nop
IL_0001: ldc.i4.s 26 //将整型26压入栈顶
IL_0003: box [mscorlib]System.Int32 //执行装箱操作。具体步骤是:先在托管堆中申请存放一个System.Int32类型变量所需要的内存空间;然后将值类型的值复制到新分配的内存空间中;最后返回新分配的内存空间的地址
IL_0008: stloc.0 //弹出堆栈上的值,并将它存储到索引值为0的局部变量中,也就是把26在内存中的地址保存到变量obj中(这个地方的26是复制的26,而不是原来的26,此时obj中存放的就已经是26的内存地址,也就是说当前obj已经指向托管堆中的实例对象)
IL_0009: ret
object obj = 20;
int res = (int)obj;
- 上边的代码先进行了一次装箱操作,然后又进行了一次拆箱操作,同样,我们通过查看IL代码来了解整个拆箱的过程
.locals init ([0] object obj,
[1] int32 num) //声明两个局部变量,object类型的obj变量和int类型的num
IL_0000: nop
IL_0001: ldc.i4.s 20 //将20压入栈顶
IL_0003: box [mscorlib]System.Int32 //执行装箱操作
IL_0008: stloc.0 //将栈中的值弹出,并将值赋值给索引为0的局部变量,也就是把20在内存中的地址赋值给变量obj
IL_0009: ldloc.0 //将索引为0的局部变量的地址压入栈顶,也就是把变量obj的地址压入栈顶
IL_000a: unbox.any [mscorlib]System.Int32 //执行拆箱操作,将object类型装换成System.Int32类型
IL_000f: stloc.1 //将堆栈中的值弹出,并将值赋值给索引为1的局部变量,也就是把20赋值给变量num
IL_0010: ret
- 装箱操作和拆箱操作是要额外耗费cpu和内存资源的,所以在c# 2.0之后引入了泛型来减少装箱操作和拆箱操作。
- 以下是对IL代码中用到的指令的解释:
名称 |
作用 |
ldc.i4.s |
将提供的 int8 值作为 int32 推送到计算堆栈上(短格式) |
box |
将值类转换为对象引用(object类型) |
stloc.s |
从计算堆栈的顶部弹出当前值并将其存储在局部变量列表中的索引值为 index 处(短格式) |
ldloca.s |
将特定索引处的局部变量的地址加载到计算堆栈上(短格式) |
unbox |
将值类型的已装箱的表示形式转换为其未装箱的形式 |