装箱(Boxing)和拆箱(Unboxing)[原创]
装箱(Boxing)和拆箱(Unboxing)
--自己总结的,有说的不好的地方,请指出
一、在说装箱和拆箱之前得先说一下变量的类型。
C#支持两种变量类型:值类型和引用类型。其中:值类型是指那些基本数据类型。如int,double,char和用struct声明的用户定义类型等;而引用类型指从基本类型构造而来的类和其它复杂数据类型。
值类型变量保存的是类型的实例,而引用类型的变量保存的不是类型的实例,保存的是实例的引用。
举个例子:创建两个值类型变量i和j:
int i=7;
int j=i;
则它们在内存中是独立保存的,值类型的变量之间没有任何联系。如果我们改变某一个值,另一个值不会有任何影响。
下面看一下引用类型的变量的情况:
我们声明并实例化下面两个变量:
myClass Class_A=new myClass();
myClass Class_B=Class_A;
它们在内存中的保存方式如下:
假设在位置0X80000保存类的实例,Class_A保存的是对类实例的引用,即保存的是地址0X80000,Class_B是对Class_A的独立引用,但保存的也是对类实例的引用。
因为类在C#中是引用类型,所以Class_A称为对myClass的引用。第一行代码先在内存中创建myClass的一个实例,并且将Class_A设置为引用该实例。因此,当将Class_A的值赋给Class_B时,Class_B保存的也是该类的实例的引用。如果我们改变Class_A中的属性,则Class_B中也会反映这些改变。
清楚了值类型和引用类型,下面就该说说装箱和拆箱了。
二、装箱和拆箱
将值类型转换为引用类型的过程称为装箱;将引用类型转换为值类型的过程称为拆箱。
2.1 装箱:
如下代码所示:
int i=123;
//object是所有其他类型的基本类型,代表的类是System.Object
object o=(object) i; //装箱
装箱的过程是:将i=123复制一份放入堆中,在栈中创建一个object o,o保存的是堆中存放i=123的地址。如下图所示:
图2.1 装箱的变化过程
下面看个例子:
Using System;
Class TestBoxing
{
Public static void
{
int i=123;
object 0=i;
i=456;
Console.WriteLine(“The value-Type value = {0}”,i);
Console.WriteLine(“The object-Type value = {0}”,o);
}
}
Output:
The value-Type value =456
The object-Type value =123
2.2 拆箱
拆箱的过程基本类似.
如下代码所示:
int i=123;
object o=(object) i; //装箱
int j=(int) o; //拆箱
过程如下图所示:
图2.2 拆箱的变化过程
拆箱的时候要注意:隐式转换的类型要跟装箱前的类型相同,否则会有异常产生。
三、总结
C# 将所有的基本数据类型都表示为对象(object),所以按照基本数据类型(object)来调用对象方法是可行的。借助于自动装箱和拆箱,可以达到此目的。所以理解装箱和拆箱就很有必要了。但是按照基本数据类型来调用对象方法有一些问题或者说缺点,例如:会造成很多垃圾内存,还会使程序的效率下降等。
在C#2.0中引入了新的语法规则――泛型(我认为是C#升级中最大的改进^_^),它很好地解决了这些问题。过些日子我会总结一下我对泛型的一些认识,希望能对看到我的博客的朋友们有些帮助。