C#装箱和拆箱

北城以北 提交于 2020-02-25 22:26:45

简单的说

装箱:值类型转成引用类型

拆箱:引用类型转成值类型

 

 

这里就执行了装箱和拆箱操作。

BoxUnbox的解释参考官网:

Box官网注释

Unbox官网注释

说说装箱的步骤:

0、将值入栈,(注意,不管这个值是在堆,还是在栈,还是在哪里,都需要先将值入栈)

1、在托管堆中分配内存。分配的内存量是值类型各字段所需的内存量,还要加上类型对象指针和同步块索引所需的内存量

2、把入栈的值,弹出栈,复制到新分配的堆里

3、返回对象地址,把地址入栈

注:两个开销字段——类型对象指针和同步块索引,所需的内存在32位应用程序上需要4+4=8个字节,64位上是16字节

看看例子:object obj = 3;装箱步骤

0、它是先将值3入栈

1、在托管堆中分配内存,在32位应用上是 4(int所需的内存) + 8 = 12个字节

2、把3弹出栈,并复制到新分配的内存堆里

3、把新地址入栈

在申请堆空间的时候,有可能会触发GC

注意,obj那个3和入栈那个3不是一个东西了。看如下代码的输出:

 

 

修改了i,但是obj的值依然是3.

 

下面看个例子:

int i = 3;
object obj = i;
Console.WriteLine(i + ", obj: " + (int)obj);

 这个代码会进行三次装箱,因为字符串的+用的是String::Concat(object, object, object);

 

 

int i = 3;
object obj = i;
Console.WriteLine(i.ToString() + ", obj: " + obj);

 这个代码只会进行一次装箱,即obj = i需要装箱,而i.ToStringobj传给Concat都不会装箱处理。

Obj不进行装箱,因为它本来就是引用类型,这个比较好理解

i.ToString()这个,涉及的就有点麻烦,参考下图:

 

 此图是《CLR via C#》 (第4版) 周靖 译 的第118页

注意:引用类型下的所有内存都是从托管堆(堆)分配,使用引用类型要注意性能问题。

这里留两个坑:

1、C#的堆和栈到底有啥区别?

2、CLR的GC机制是啥?

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!