在讨论装箱和拆箱之前,首先要回忆一下计算机的内存组织。操作系统和CLR一般将容纳数据的内存划分为2个独立的区域,每个区域都采取不同的方式来进行管理,这2个区域就是堆栈和堆。变量一般存储在堆栈中,对象存储在堆中。
值和引用的概念。如果将一个变量拷贝给另一个变量,这2个变量是没有联系的,修改一个不会影响另一个。但是引用就不同了,引用或者说句柄,是在堆栈中开辟一个空间来指向位于堆中的对象,引用可以说成是C++中的指针,但是有不完全是指针,指针可以指向任何内存快,而引用只能指向特定的内存快,是要限制类型的。如果有多个句柄指向同一个对象,那么只要一个句柄对对象作过什么修改,其他的句柄一样能体现出来。这个一定要搞清楚啊。
ref和out关键字。谈到值和引用的时候不得不谈一下这2个关键字。向方法传递一个实参时,对应的参数会使用实参的一个副本来初始化,不管是值类型还是引用类型。但是,有时候,我们可能有这样的需求,我希望实参改变,虽然传得是副本,但是同时我希望实参也改变,可以这样来考虑,我希望通过副本来引用实参,达到副本和实参同时改变的目的。只需要在参数前加上ref就行了。out 关键字:有时候不希望自己来初始化某个局部变量,希望通过某个方法来初始化,这个情况就使用out关键字。关于out和ref在实际项目中的用途还需要不断尝试。代码如下:
ref:
static void Main(string[] args)
{
int arg = 42;
DoWork(ref arg);
Console.WriteLine(arg);//输出43
}
static void DoWork(ref int param)
{
param++;
}
out:
static void Main()
{
int arg;//即使没有初始化也不会报错
DoWork(out arg);
Console.WriteLine(arg);//输出42
}
static void DoWork(out int param)
{
param = 42;
}
装箱就是把值赋给object类型的变量 object o = 42;而拆箱就是将已经引用了装箱值得object引用强制转换成值类型 int i = (int)o;object对象是一切对象的父类,所以他存储在堆上,object o = 42 需要将42从堆栈拷贝到堆中才能使用。这个过程需要耗费很大的资源。为了访问已经装箱(存在堆中的值)的值,当然需要拆箱,也就是强制类型转换,将堆中的值又重新拷贝到堆栈。代码如下:
static void Main()
{
int i = 42;
object o = i;
Console.WriteLine(o);
int j = (int)o;
Console.WriteLine(j);
}
装箱和拆箱的概念就是如此,但是怎么也没碰到过某种需求需要用他们来实现的,对了装箱跟泛型是异曲同工的,泛型过段时间再写。