可能的重复:
为什么我们需要C#中的拳击和拆箱?
什么是拳击和拆箱,交易折扣是什么?

在c#中,doe坐着是什么意思:“盒子和unox”?

在这里,我从MSDN提取了文本。

但是这种便利是有代价的。将添加到ArrayList的任何参考或值类型都隐含地升至对象。如果这些项目是价值类型,则将它们添加到列表中时必须装箱,并在检索时将其取消装箱。铸件和拳击和拆箱操作都降低了性能;在您必须在大型收藏中迭代的情况下,拳击和拆箱的效果可能非常重要。

谢谢!

有帮助吗?

解决方案

这是一个更详细的解释,着眼于通用语言运行时的内部。

首先,让我们在 价值类型参考类型:

  • 价值类型在 并将其副本传递给了称为方法
  • 托管堆 堆栈仅保留其位置的指针(引用)。位置而非对象传递给称为方法

如果您不知道堆栈是什么(不要冒犯),则是一个存储区域,在方法和呼叫者功能的地址中保存本地变量 return 指示(只是简要介绍并提供一般答案)。当您调用方法时,堆栈上的足够区域是 静态 分配给它,因此堆栈分配始终称为静态分配。

相反,堆是一个与堆栈分离的内存区域, 财产 在运行过程中,必须首先向操作系统索取分配的过程,这就是为什么称为 动态分配 (例如,如果您不在IF语句中运行,则可能不会为您的过程分配内存,而是总是分配堆栈)。

只是为了在堆和堆栈上做出最后一个示例:在诸如C ++之类的语言中,声明 int[100] a; 静态分配100*8字节在堆栈上(假定64位系统),而 int* a = new int[100]; 在堆栈上宣布一个8个字节(在64位系统上)区域,并在堆上要求更多的字节(如果和地方)。

现在让我们谈谈C#:

拳击

由于int是一种值类型,并且在堆栈上分配了int,当您将其投射到对象或任何其他参考类型时(实际上没有其他参考类型,int可以继承,但这是一般规则)必须必须变为参考类型。因此,分配了堆上的新区域,对象是 盒子 它的内部和堆栈将其指向它。

拆箱

恰恰相反:当您有一个参考类型(例如对象),并希望将其施放为一个值类型,例如int,必须将新值保存在堆栈上,因此CLR变为堆, 未盒子 值并将其复制到堆栈中。

换句话说

记住 int[]int* 例子?简而言之 int 在C#中,运行时期望其堆栈位置为 保持价值 但是当你有 object, ,它预计其真正的价值将位于堆栈指向的堆位置。

其他提示

.NET框架中有两种不同类型。

估算型例如int,double,单身

参考型ArrayList列表,还有更多

类型的变量 估算型 存储在堆栈中引用分型 变量存储在堆中

类型的变量 估算型 存储值引用分型 变量存储对值的引用

因此,如果您复制 值类型 变量 - 有一个 真实的副本 一个值,但如果您复制一个 引用类型 可变 - 您将得到一个 附加参考 到同一变量。

您的问题中的拳击意味着,将处理一个valueType变量(例如int),被认为是参考类型变量 - .NET将其带入新的 盒子. 。因此,它将被封装在堆中,并将有参考。

如果您希望该值再次在ValueType变量中再次出现 Unbox 它(将其从开箱即用)。因此,该值将被从堆中取出 - 并再次存储/给出堆栈。

ArrayList仅存储对象。用于参考类型(喜欢 String)这没问题,但是对于valueType(int,dateTime,..)是。

在将它们存储为普通对象之前,需要将这些估算型转换为对象。这种“转换为对象”称为“拳击”,需要一点时间。

当您读回值时,您需要从对象转换为 int (或者是什么)。这称为“拆箱”。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top