C#中的数据分为值类型和引用类型两种
值类型
直接包含值,不能为null,可以在栈上分配。复制时直接复制一份内存
除string外的所有基本类型,以及用struct定义的结构体
引用类型
变量指向数据存储的位置,在堆上分配,复制时传递的是地址,多个变量可以引用同一个对象。
装箱就是将值类型转换为对应的引用类型,
步骤:
1.在堆上分配内存,用于存放值类型的数据以及少许额外开销
2.内存复制,值类型数据拷贝到堆上
3.更新对象或接口引用,指向堆上的位置
拆箱则是相反的操作,
根据定义,CIL指令unbox只是对堆上的数据进行解引用,并不包括从堆复制到栈的动作,
但在C#语言中,大多数时候都会在拆箱后发生一次内存拷贝。
频繁的装箱和拆箱会引起较大的性能开销,因此在一些循环中尤其需要注意这一点。
以下为装箱、拆箱的例子
int num = 10;
object obj = num;
int num2 = (int)obj;
IL反汇编器查看如下:
.maxstack 1
.locals init ([0] int32 num,
[1] object obj,
[2] int32 num2)
IL_0000: nop
IL_0001: ldc.i4.s 10
IL_0003: stloc.0
IL_0004: ldloc.0
IL_0005: box [mscorlib]System.Int32
IL_000a: stloc.1
IL_000b: ldloc.1
IL_000c: unbox.any [mscorlib]System.Int32
IL_0011: stloc.2
IL_0012: ret