装箱和拆箱
所谓的装箱和拆箱呢,也就是值类型和引用类型之间的转换.
而为什么会有转换呢?是因为这两个不在同一个环境,一个在线程栈,一个在托管堆上
什么是值类型
值类型也就是一般不包含指向实例的指针,一般用struct来标志,反之就是引用类型(class)
装箱
和现实中联系起来,也就是将某个东西进行打包,装饰.具体步骤如下,
>计算需要装箱的值类型结构的大小,然后加上类型对象指针和同步索引块的大小,并在托管堆上分配内存
>然后将值类型逐位进行复制
>然后返回装箱对象的地址
就这样一个值类型就被装箱成了引用类型
拆箱
具体步骤:
>值类型获取装箱类型的各个字段的引用
>逐位进行复制
struct(结构)
//这就是一个简单的结构 struct d1 { public int i; }
那么这个结构是用来干什么的呢?我们不是有了一个引用类型class?
当然是因为class有不足之处才有了结构,当然这只是一个方面
>由于引用对象生存在托管堆上,每次你new一个实例,就会分配内存,而struct是直接赋值
>每个堆对象都会有附加的两个对象, 类型对象指针和同步索引块(这也是为什么值类型不能lock的根本原因)
>为了对应C语言的union
为了可以控制struct字段在内存中的位置,C#提供了[StructLayout()],用这个属性来标识CLR如何排布字段
>LayoutKind.Auto CLR自动分配
>LayoutKind.Explicit 可以使用 [FieldOffset()]进行分配
>LayoutKind.Sequential 可以是不连续
然后我们来看一个例子
[StructLayout(LayoutKind.Explicit)] struct dd { //联合成员0-0 [FieldOffset(0)] public int i; [FieldOffset(0)] public int j; }
执行代码:
static void Main(string[] args) { dd d; d.i = 1; d.j = 2; Console.WriteLine("i: "+d.i.ToString()); Console.WriteLine("j: " + d.j.ToString()); Console.Read(); }
结果图: