装箱和拆箱概念,给值类型和引用类型相互转换搭起了一座桥梁,即:value_type值可以转换成object类型的值,反过来也可以。
在C#语言规范中,有一个例子,可以拿来供大家理解:我们可以设想有一个泛型装箱类Box<T>,他的声明和行为如下:
sealed class Box<T> : ValueTuple { T value; public Box(T t) { this.value = t; } }
当我们进行下面一个常见的装箱操作时:
int a = 10; object box = a;
其实就可以当成:
int a = 10; object box_box = new Box<int>(a);
以上便是装箱操作的过程的拆解。我们要知道并不存在这样一个Box<T>装箱类。
下面的例子也是装箱操作,从它的输出可以看出,值类型和引用类型,转换前后其实没有关系了。
struct MyPoint { public int x, y; public MyPoint(int a,int b) { this.x = a; this.y = b; } } private static void Main(string[] args) { MyPoint myPoint = new MyPoint(10,2); object point = myPoint; myPoint.y = 20; Console.WriteLine(((MyPoint)point).y); }
输出结果:2;
因为:mypoint是值类型,它赋值给point时是一种装箱操作。mypoint数值在栈内存中复制了一份放到了堆中point的实例中。操作mypoint的属性对于point对象再无任何影响。假如把MyPoint声明为class类型,那么输出结果就是20,因为此时mypoint和point引用的是同一实例。
参照在装箱操作中假想的装箱类,以下普通的拆箱操作:
object o = 10; int y = (int)o;
便等同于:
object box = new Box<int>(10); int yy = ((Box<int>)box).value;//从实例中找到int类型的值value,复制给变量yy中
可以看出:拆箱操作,经历了将值从堆内存中搬运到栈内存中的一个过程。
总结:
无论是装箱操作还是拆箱操作,都涉及到数据在堆和栈之间进行来回搬运,这对程序性能是一种损耗。所以在编码过程中尽量避免装箱和拆箱操作。
原文:https://www.cnblogs.com/bigbosscyb/p/13513626.html