学习笔记:浅谈C#装箱和拆箱

装箱和拆箱是什么
装箱:将数据由值类型转换为引用类型
拆箱:将已经装箱的数据由引用类型转换回原本的值类型

举例:

int n = 10;
object o = n;//装箱

这里就做了装箱的操作,n的10是int类型的,o的10是object类型的
原本只有在栈上一块空间n存放了10。
现在又在堆中开辟了一块空间存放了10(还有同步块索引和方法表指针),在栈中存放了指向此堆中地址的引用。

int n = 10;
object o = n;//装箱
int n2 = (int)o;//拆箱

拆箱操作,复制堆上的10再到栈上开辟了一块空间。

那来试试,将int装箱再拆箱成double类型可以吗?

int n = 10;
object o = n;//装箱
double n2 = (double)o;

此时编辑器不报错,运行一下,报错了
在这里插入图片描述
原因是装拆箱的类型不一致。(这边猜测,系统是根据原数据的占用空间的大小来判断是否和装箱前类型一致,等一个大佬来指正)

判断是否发生了装箱或拆箱
首先判断这两种数据类型是否存在继承关系,再判断是否发生值类型到引用类型的转换
注意
什么类型装的箱,就得拿什么类型拆箱

例题

1.以下的代码发生了几次装箱/拆箱?

int n = 10;
object o = n;
n = 100;
Console.WriteLine(n+","+(int)o);

看起来是1次装箱?
其实是3次装箱1次拆箱
首先object o = n;1次装箱,这里不知道的话建议从头再看一次。
(int)o 1次拆箱。
然后Console.WriteLine(n+","+(int)o);中发生了两次装箱。
n+","+(int)o 这里是三个字符串用加号拼接,其实隐式的对n和(int)o调用了string.Contact()方法。相当于Console.WriteLine(string.Contact(n,",",(int)o));
而int型是不能作为string.Contact()方法的参数的,所以系统对两个int类型n和(int)n进行了装箱操作,装箱成object类型了。
注:
在这里插入图片描述

2.以下的代码发生了装箱了吗?

int n = 10;
Console.WriteLine(n);

没有,因为Console.WriteLine() 有int型参数的重载,不需要转换类型
在这里插入图片描述
3.以下的代码发生了装箱了吗?

int n = 10;
IComparable com=n;

发生了,有继承关系,值类型到引用类型转换了
在这里插入图片描述
4.以下的代码发生了装箱了吗?

int n = 10;
string s1 = n.ToString();
string s2 = n.GetType().ToString();
Console.WritelLine(s1+"\t\t\t"+s2);

发生了一次装箱,在n.GetType()
因为GetType()方法是object的方法,所以需要将int类型的n装箱,然后调用。
而int类型包含ToString()方法,所以n.ToString();不装箱
最后一行,三个参数都是string类型,直接拼接没有数据类型转换,不装箱。

装箱的缺点
装箱时,会生成新的引用对象,会有时间损耗,接下来对比一下装箱和不装箱的时间损耗

这里用非泛型的ArrayList和泛型的List做对比

装箱:
在这里插入图片描述
不装箱:
在这里插入图片描述
可以看到,装箱耗费的时间基本是不装箱耗费时间的十倍,可以说是损耗相当大了,所以说要尽量避免装箱

如何避免装箱
1.如上面的例子,使用泛型去避免装箱。
2.如上上面的例题,比如方法参数是object,传参会经常出现装箱的情况。
这时候就要使用方法重载去避免装箱。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值