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类型。