C#装箱和取消装箱分析

 
把值类型的实例转换为引用类的实例,就称为装箱,其逆过程称为取消装箱。
在C#中,这种情况常常在我们未意识的情况下发生的。但是,理解发生了什么是很重要的,所以先介绍一下这两个过程:
1, 把值类型转换为对象
考虑下面代码
ArrayList myArrayList = new ArrayList();
 
myArrayList.Add(new Money(2500.0));
 
ArrayList是一个标准的集合类,它包含一个对象的引用集合。这些对象必须是引用类型,所以必须位于托管堆上。而方法Add()需要一个对象作为参数。
Money是一个结构 是值类型的实例,要把它添加到ArrayList中,CLR会在托管堆上自动创建Money实例的一个装箱副本。此时,装箱表示CLR给实例添加了一个包装器,使它的显示和行为类似于一个引用类型。这是自动进行的。
 
装箱的对象包含值对象的数据副本。如果装箱的对象修改了,不会影响原来的值对象。同样,如果原来的值对象修改了,也不会影响装箱的对象。这正是值类型所期望的。
 
当从ArrayList中检索值时,可以使用[]语法返回托管堆上的对象的引用。例如:
Money myMoney = (Money) myArrayList[0];
在使用显示类型转换把它赋予Money实例时,CLR就会从装箱的对象中提取该值,把它复制到本地的Money实例中。这术就有了该值的一个副本,修改它不会影响原来的值和堆上的装箱值。这就是取消装箱的达程,在C#中它也是自动完成的。
 
2, 装箱和取消装箱的过程
C#自动完成装箱和取消装箱过程,可是在这个过程中会增加系统开销。下面深入的探讨一下它们的具体过程。
当把Money值类型添加到ArrayList中时发生的情况:
(1)    首先利用new运算符,创建一个基于栈的Mnoey类型
(2)    C#编译器认为,AeeayList类的Add()方法需要一个引用类型,而不是一个值类型,所以调用MSIL代码执行装箱操作
(3)    在托管堆上分配内存,这包括Money结构中的字段需要的内存,以及把装箱的类型建立为引用类型所需要的额外内存
(4)    基于栈的Money实例是利用new运算符创建的,其上的字段要逐个字节地复制到新分配的堆内存上
(5)    最后,返回堆上保存的对象的地址,并传给ArrayList类的Add()方法
取消装箱的过程:
(1)    在栈上为myMoney变量分配内存,调用默认的构造函数来初始化面员字段
(2)    检查装箱引用,如果为NULL 则抛出NullReferenceException异常
(3)    根据显示类型转换过程中的声明 来检查装箱对象的类型 如果不是 则抛出InvalidCastException异常
(4)    最后得到堆上装箱值类型的一个指针,把Money字段的内容复制到栈的变量中
可以看出来,如果应用程序中执行了许多装箱和取消装箱过程,那么性能和内存使用方面的开销就会狠大
3, 其他装箱的情况
上面的例子是把值类型作为参数传给一个需要引用类型的方法。其实还有其它地方会发生装箱操作。
只要隐式或显式地把值类型的实例转换为引用类型,也会发生装箱操作。例:
int number = 43;
object o = nember;               //装箱
int anotherNumber = (int)o;        //取消装箱
 
在把值类型转换为接口时,也会发生装箱操作。
 
在检查对象的类型时,例
Money someMoney = new Money(4.0);
Type t = someMoney.GetType();           
这种情况上,someMoney也装箱了,这是因为Money没有直接实现GetType();因为它继承了System.ValueType. 为了实现这个方法调用,CLR需要一个指向Money方法表的指针,它只能通过装箱someMoney来获得。
 
 
总结:最好是限制装箱和取消装箱的次数,如果应用程序进行许多这样的操作,则把数据类型定义为类比定义为结构更有效。
 
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值