C#实践教程(第2版)
上QQ阅读APP看书,第一时间看更新

2.6 装箱和拆箱

装箱和拆箱是一个抽象的概念,通过装箱和拆箱的功能,可以允许值类型的任何值与Object类型的值相互转换,将值类型和引用类型连接起来。

2.6.1 装箱

装箱是值类型到Object类型或到此值类型所实现的任何接口类型的隐式转换,用于在垃圾回收堆中存储值类型。

装箱实际上是指将值类型转换为引用类型的过程,装箱的执行过程大致可以分为以下三个阶段:

(1)从托管堆中为新生成的引用对象分配内存。

(2)将值类型的实例字段拷贝到新分配的内存中。

(3)返回托管堆中新分配对象的地址,该地址就是一个指向对象的引用了。

如下代码演示了如果将int类型的变量val进行装箱操作,然后将装箱后的值进行输出:

int val = 100;
object obj = val;                            //装箱
Console.WriteLine (“对象的值 = {0}", obj);   //输出结果

装箱操作生成的是全新的引用对象,这会损耗一部分的时间,因此会造成效率的降低,所以应该尽量避免装箱操作。一般情况下,符合下面的情况时可以实施装箱操作:

□ 调用一个含Object类型的参数方法时,该Object可以支持任意的类型以方便通用,当开发人员需要将一个值类型(如Int32)传入时就需要装箱。

□ 使用一个非泛型的容器,其目的是为了保证能够通用。因此可以将元素类型定义为Object,于是如果要将值类型数据加入容器时需要装箱。

2.6.2 拆箱

拆箱也叫取消装箱,它是与装箱相反的操作,它是从Object类型到值类型或从接口类型到实现该接口的值类型的显式转换。

拆箱实际上是指从引用类型到值类型的过程,拆箱的执行过程大致可以分为以下两个阶段:

(1)检查对象实例,确保它是给定值类型的一个装箱值。

(2)将该值从实例复制到值类型变量中。

如下示例代码演示了基本的拆箱操作:

int val = 100;
object obj = val;                      //装箱
int num = (int) obj;                   //拆箱
Console.WriteLine ("num: {0}", num);   //输出结果

注意

当一个装箱操作把值类型转换成一个引用类型时,不需要显式地强制类型转换;而拆箱操作把引用类型转换到值类型时,由于它可以强制转换到任何可以相容的值类型,所以必须显式地强制类型转换。