接着上一篇的未完待续,这篇总结一下值类型和引用类型的转化问题——拆箱装箱
装箱:值类型——引用类型,系统会在托管堆中生成一份堆栈中值类型对象的副本。
拆箱:引用类型——值类型,从托管堆中将引用类型所指向的已装箱数据复制会值类型对象。
我在上篇博客中写了值类型变量值在栈中,而引用类型数据实在托管堆上,所以装箱就相当于把栈上的数据赋值到托管堆上,而拆箱就相当于把托管堆上的数据复制到栈上。我们可以将托管堆想象成一个快递的箱子,装箱呢就是你去寄快递,放进去一个你要寄得东西(数据),拆箱呢就是你去取快递,拿出来一个东西(数据)。这样想仅仅是方便记忆。
最近看了一本书,是从内存的角度深入分析了一下这个过程:
class Program
{
static void Main(string[] args)
{
//首先定义一个值类型
int i = 3;
//装箱操作,因为要往箱子里装,所以先分配好一块内存来放这个数据也就是o
object o = i;
//拆箱操作
int y = (int)o;
}
}
装箱的操作分为三步:
(1)内存分配:在托管堆中分配好内存空间以存放复制的实际数据。
(2)完成实际数据的复制:将值类型实例的实际数据复制到新分配的内存中。
(3)地址返回:将托管堆中的对象地址返回给引用类型变量。
但是拆箱和装箱的操作对于系统性能是一次巨大的挑衅,因为仅仅一个装箱的操作就分了这么多步骤,两个过程都要进行数据的复制,一个系统要拆装个好些回,还不得慢死啊。而且在这个过程中会产生多个不必要的对象,导致了系统性能的降低。所以为了避免拆装箱的操作,我们最好使用泛型来进行编程。上一篇也提到了这一点。下篇博客就举个栗子,看看值类型和引用类型在传递参数的过程中到底有什么不同~