5.1.3 装箱

之所以再次讨论装箱,是因为装箱也属于类型转换的知识范畴。我们先来看一段示例代码,如代码清单5-4所示。

代码清单5-4 装箱


1 namespace ProgrammingCSharp4

2{

3 class Boxing

4{

5 public void DoSomething()

6{

7 int x=10;

8 object obj=x;

9}

10}

11}


第7行声明了一个int型变量x,并初始化为10。接着第8行声明了一个object类型obj,并使用x为其初始化,这里既是我们在第1章讲的装箱,也是本章讲的类型转换,其本质还是类型转换,即将int型“装箱”为object类型,这个装箱的过程即是隐式的类型转换。

我们仍然通过查看上述代码编译生成的CIL代码来观察装箱的具体过程,CIL代码如代码清单5-5所示。

代码清单5-5 DoSomthing()函数的CIL代码


1.method public hidebysig instance void DoSomething()cil managed

2{

3//Code size 12(0xc)

4.maxstack 1

5.locals init([0]int32 x,

6[1]object obj)

7 IL_0000:nop

8 IL_0001:ldc.i4.s 10

9 IL_0003:stloc.0

10 IL_0004:ldloc.0

11 IL_0005:box[mscorlib]System.Int32

12 IL_000a:stloc.1

13 IL_000b:ret

14}//end of method Boxing:DoSomething


这里只关注与装箱相关的代码,对CIL有兴趣的读者可以自行查找相关资料进行学习。

代码清单5-5 的第11行是重点,box指令指示把栈中的int型(值类型)变量装箱为引用类型(object)。经过装箱这一过程后,原来的值类型的变量就不存在了,取而代之的就是装箱后的引用类型的变量。

另外,枚举类型经过装箱以后成为System.Enum类型,因为System.Enum类是枚举类型的基类。而结构类型和枚举类型装箱后则为System.ValueType类型,原因一样,因为System.ValueType类型是所有结构类型和枚举类型的基类。

在本节的最后,我们对装箱的类型转换做个总结,如下:

❑值类型可隐式转换到object类型或System.ValueType类型;

❑非Nullable值类型可隐式转换到它实现的接口;

❑枚举类型可隐式转换到System.Enum类型。