C#:装箱与拆箱

装箱和拆箱概念,给值类型和引用类型相互转换搭起了一座桥梁,即:value_type值可以转换成object类型的值,反过来也可以。

1、装箱操作:允许将vaule_type隐式地转换成reference_type。

装箱操作发生时,一般遵循下面步骤:创建一个对象实例,将value_type值复制到这个实例里面。

在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>装箱类。

关于装箱,我们要注意一点:装箱转换隐含着“复制”概念。我们常见的从引用类型referece_type到object类型的转换,可不是装箱转换。

下面的例子也是装箱操作,从它的输出可以看出,值类型和引用类型,转换前后其实没有关系了。

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引用的是同一实例。

2、拆箱操作:也称取消装箱操作,它将reference_type类型的值显示转换成了value_type类型的值。

拆箱操作发生时经历一下步骤:首先检查实例中是否存在给定的值类型的值,然后把这个值从实例中复制出来。

参照在装箱操作中假想的装箱类,以下普通的拆箱操作:

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