装箱和拆箱

 
装箱 (boxing) 和拆箱 (unboxing) C# 类型系统中重要的概念。它通过允许任何数值类型的数据被转换为任何形式类型的对象提供了数值类型和引用类型间的紧密联系。装箱和拆箱使得对在其中任何类型都可以最终被看作对象的类型系统的统一的观察变为可能。
装箱转换允许任何数值类型可以隐式地转换为 object 类型或任何由数值类型实现的接口类型。装箱一个数值类型的数据包括对对象实例的定位和把数值类型数据拷贝到那个实例中。
装箱数值类型的数据的实际过程,可以通过想像一个对那种类型的装箱类的实际例子来解释。对于数值类型 T ,装箱类要按下面定义:
class T_Box
{
T value;
T_Box(T t) {
     value = t;
}
}
对于类型 T 的数值 v 的装箱现在由执行表达式 T_Box(v) 来代替 , 并且返回类型为 object 的结果实例。这样,语句
int i = 123;
object box = i;
从概念上符合
int i = 123;
object box = new int_Box(i);
如上面的 T_Box int_Box 的装箱类型实际不存在,而被装箱数据的动态类型实际上并不是一个类类型。作为替代,类型 T 的一个被装箱的数据有动态类型 T ,而使用 is 操作符的动态类型检查可以很方便地引用 T 。例如,
int i = 123;
object box = i;
if (box is int) {
Console.Write("Box contains an int");
}
将在控制台输出字符串 Box contains an int
装箱转换隐式地把被装箱的数据进行了备份。这与从引用类型到 object 类型的转换不同,在那里数据一直引用相同的实例,并被认为几乎不从类型 object 派生。例如,给出声明
struct Point
{
public int x, y;
public Point(int x, int y) {
     this.x = x;
     this.y = y;
}
}
下面的语句
Point p = new Point(10, 10);
object box = p;
p.x = 20;
Console.Write(((Point)box).x);
因为在发生把 p 赋值给 box 的隐含装箱操作时, p 被拷贝,所以将在控制台上输出数值 10 。如果 Point 被声明为一个类,因为 p box 将引用相同的实例,就会输出 20
拆箱转换允许任何 object 类型或从任何由数值类型实现的接口类型,可以显式地转换为任何数值类型。一个拆箱操作由几部分动作组成,首先检查 object 实例是一个所给数值类型的被装箱数据,然后把数值从实例中拷贝出来。
参考前面章节描述的假象的装箱类型,从对象 box 到数值类型 T 的拆箱转换包括执行表达式 ((T_Box)box).value 。这样,语句
object box = 123;
int i = (int)box;
从概念上符合
object box = new int_Box(123);
int i = ((int_Box)box).value;
对于为了在运行时提供数值类型的拆箱转换,源变量数据必须是一个指向一个早先对那个数值类型数据打包创建的对象。如果源变量是 null 或引用一个不相关的对象,就会抛出一个 InvalidCastException 错误。
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值