Box和UnBox是什么意思?

时间:2011-01-25 14:34:00

标签: c# .net boxing unboxing

  

可能重复:
  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。如果是的话   值类型,它们必须装箱时   它们被添加到列表中,并且   检索时取消装箱。都   铸造和拳击和   拆箱操作减少   性能;拳击和拳击的影响   拆箱可能非常重要   您必须迭代的场景   大集合。

谢谢!

3 个答案:

答案 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(或者它是什么)。这称为“拆箱”。