可能重复:
Why do we need boxing and unboxing in C#?
What is boxing and unboxing and what are the trade offs?
在C#中,doe的意思是:“Box and UnBox”?
这是MSDN的摘录,我在那里创建了Text。
但这种便利需要付出代价。 任何引用或值类型 添加到ArrayList是隐式的 upcast to Object。如果是的话 值类型,它们必须装箱时 它们被添加到列表中,并且 检索时取消装箱。都 铸造和拳击和 拆箱操作减少 性能;拳击和拳击的影响 拆箱可能非常重要 您必须迭代的场景 大集合。
谢谢!
答案 0 :(得分:27)
以下是一个更详细的解释,介绍了公共语言运行时的内部。
首先,让我们区分值类型和引用类型:
如果您不知道堆栈是什么(不要被冒犯),它是一个存储区域,用于保存方法中的局部变量和用于return
指令的调用函数的地址(只是为了简短并提供一般答案)。当您调用方法时,堆栈上的足够区域静态分配给它,因此堆栈分配始终称为静态分配。
堆是一个与正在运行的进程的堆栈 property 分开的内存区域,其中必须首先向操作系统请求分配,这就是为什么它被称为动态分配(例如,如果不在if语句中运行,则可能不会为您的进程分配内存,而是始终分配堆栈。)
只是在堆和堆栈上做一个最后的例子:在C ++等语言中,声明int[100] a;
在堆栈上静态分配100 * 8个字节(假设为64位系统),而int* a = new int[100];
声明堆栈上的8个字节(在64位系统上)区域在堆上请求800个字节,如果可用的话。
现在让我们谈谈C#:
由于int是一个值类型,并且是在堆栈上分配的,当你将它转换为object或任何其他引用类型时(实际上没有其他int可以继承的引用类型,但它是一般规则)值必须成为参考类型。因此,堆上的新区域被分配,对象在其中被加框,并且堆栈中包含指向它的指针。
恰恰相反:当你有一个引用类型,比如object,并希望将它转换为一个值类型,比如int,新值必须保存在堆栈上,所以CLR转到堆,< em> un-boxes 该值并将其复制到堆栈中。
还记得int[]
和int*
示例吗?简单地说,当您在C#中有int
时,运行时期望其堆栈位置保持值,而当您拥有object
时,它期望其实际值在堆栈指向的堆位置。
答案 1 :(得分:1)
.net Framework中有两种不同的类型。
<强>值类型强> 例如int,double,single
<强>引用类型强> 数组列表 名单 还有很多很多
ValueTypes 类型的变量存储在Stack中 ReferenceTyped 变量存储在堆
中ValueTypes 类型的变量存储VALUE ReferenceTyped 变量将REFERENCE存储到值
因此,如果您复制 ValueType 变量,则值为实际副本 但是如果您复制 ReferenceType 变量 - 您将获得一个附加引用到SAME变量。
在你的问题中装箱意味着,一个valueType变量(例如int)将像参考类型变量一样处理 - .net将其赋予一个新的框。所以它将封装在堆中,并且会有引用。
如果您希望该值再次位于valueType变量中,则必须取消装箱(将其从包装盒中取出)。因此,该值将从堆中取出 - 并再次存储/提供给堆栈。
答案 2 :(得分:0)
ArrayList仅存储对象。对于引用类型(如String
),这没有问题,但对于ValueType(int,DateTime,..),它是。
在将这些值类型存储为普通对象之前,需要将这些类型转换为对象。这种“转换为对象”被称为“拳击”,需要一点时间。
当你读回值时,你需要从Object转换为int
(或者它是什么)。这称为“拆箱”。