简单的来说:装箱就是值类型转换为引用类型;拆箱就是引用类型转换为值类型。
值类型:包括原类型(Sbyte、Byte、Short、Ushort、Int、Uint、Long、Ulong、Char、Float、Double、Bool、Decimal)、枚举 (enum) 、结构 (struct)。 引用类型包括类、数组、接口、委托、字符串等。
装箱:值类型到引用类型或到此值类型所实现的任何接口类型的隐式转换。例如:
int temp = 3;
System.Object obj = temp;
其中,temp为值类型,在栈中分配;当分配obj这个引用类型时,我们需要在堆中分配一个obj对象,然后把temp值赋给它,这么一系列的过程就是装箱的过程。
拆箱:从引用类型到任意值类型的显式转换。与装箱不同,拆箱式显示转换。例如:
int temp = 3;
System.Object obj = temp;
int i = (int) obj;
拆箱过程中,首先来确定对象obj为一个值类型的装箱值,然后把值赋给值类型。
隐式转换总会成功的情况,不会抛出异常:
1)从派生类到基类;
2)从派生接口到基接口;
3)从类到接口(该类实现了接口);
4)从Null到任何类。
显式引用转换,以下可能抛出异常,转换不一定成功:
1)从基类到派生类;
2)从接口到接口(基接口到派生接口或者俩接口没有关系);
3)从接口到类(该类实现了该接口或该类未封闭);
4)从类到接口(该类未实现该接口且该类未封闭)。
以上简单的介绍了拆箱和装箱的定义,下面就来讨论一下装箱和拆箱与堆和栈怎样使用?
其中值类型是在栈中分配内存,本身的声明就是一个初始化的过程,其不需要进行垃圾回收,只要超出所定义的作用范围会自动释放内存,而引用类型则是在堆中分配的,和java一样,在堆中分配内存,而其托管堆进行垃圾回收。当两种数据类型进行转换时就引出了装箱/拆箱。
比较装箱和拆箱的优缺点:
装箱和拆箱虽然满足了两种类型之间的转换。但是从装箱的过程中不难看出,每次装箱时要在堆中new一个新的对象,当量特别大是肯定会大大影响程序的效率。所以,在应用中,我们应该尽量避免装箱操作。
了解了装箱和拆箱的操作,我们可以清楚的明白:装箱操作会导致数据在堆和栈上进行拷贝,频繁的装箱操作会性能损失。而相比而言拆箱过程对性能损耗还是比较小的。