在有些情况下,当一个实例 值类型需要被视为一个 实例引用类型。 对于 像这样的情况,值的类型 实例可以被转换成 参照类型的实例通过 处理所谓的拳击。当一个值 类型的实例是盒装、储存是 在堆上分配和 实例的价值是拷贝到这 空间。一个参考这个存储是 放在栈。装箱的价值 是一个对象,基准类型 包含的内容的价值 类型的实例。

理解。净是常见类型的系统

维基百科 有一个例子Java。但在C#什么某些情况下,一个人必须要框值的类型?或者一个更好的/相似的问题是,为什么一个想要保存一个值型堆上(装箱)而不是在栈?

有帮助吗?

解决方案

通常,您通常希望避免装箱值类型。

但是,很少有这种情况有用。例如,如果您需要定位1.1框架,则无法访问泛型集合。在.NET 1.1中使用集合需要将您的值类型视为System.Object,这会导致装箱/取消装箱。

在.NET 2.0+中仍然存在这种情况。只要您想利用所有类型(包括值类型)可以直接作为对象这一事实,您可能需要使用装箱/拆箱。这有时很方便,因为它允许您在集合中保存任何类型(通过在通用集合中使用对象而不是T),但一般来说,最好避免这种情况,因为您正在失去类型安全性。但是,经常发生拳击的一种情况是,当你使用反射时 - 反射中的许多调用在处理值类型时需要装箱/拆箱,因为事先不知道类型。

其他提示

几乎没有充分的理由故意选择值类型。包装值类型的原因几乎总是将其存储在一些非类型感知的集合中。例如,旧的 ArrayList 是一个集合对象,它们是引用类型。收集整数的唯一方法是将它们作为对象封装并将它们传递给ArrayList。

如今,我们有通用集合,所以这不是一个问题。

拳击通常会在.NET中自动发生;通常当您将值类型传递给期望引用类型的东西时。一个常见的例子是string.Format()。将原始值类型传递给此方法时,它们将作为调用的一部分进行装箱。所以:

int x = 10;
string s = string.Format( "The value of x is {0}", x ); // x is boxed here

这说明了一个简单的场景,其中值类型(x)被自动装箱以传递给期望对象的方法。通常,您希望尽可能避免装箱值类型...但在某些情况下它非常有用。

有趣的是,当您在.NET中使用泛型时,当用作参数或类型成员时,值类型不会被加框。这使得泛型比旧的C#代码(例如ArrayList)更有效,它将{object}视为与类型无关的所有内容。这增加了使用泛型集合的另一个原因,例如List<T>Dictionary<T,K> over ArrayListHashtable

我会推荐你2个不错的文章的埃里克利珀特

http://blogs.msdn.com/ericlippert/archive/2009/04/27/the-stack-is-an-implementation-detail.aspx

http://blogs.msdn.com/ericlippert/archive/2009/05/04/the-stack-is-an-implementation-detail-part-two.aspx

这里是报价,我100%的同意

使用堆为你的价值 类型只是一个优化的 CLR执行您的代表。相关的功能价值的类型 他们的语义是 复制的价值,而不是有时 他们的释放可以通过优化 运行时。

在99%的应用程序开发者应该不关心你为什么值类型是在堆,而不是在堆和什么样的性能增加我们在这里。伸心中已有非常简单的规则:

  1. 避免拳/拆箱的时候不 有必要,可使用仿制药的藏品。大多数问题发生不当你 定义自己的类型,但是当你 使用现有类型的不正确 (Microsoft定义的或者你的 同事)
  2. 让你的价值的类型 简单的。如果你需要有一个结构 与10-20个领域,我想你'ld 更好地创造一类。想象一下,所有的 这一领域将复制的每个时间 当你偶尔传递一个 功能的价值...
  3. 我不认为这是非常有用 值类型的参照类型 领域内。像的结构与 String和对象领域。
  4. 定义是什么类型取决于你需要的 所需的功能,不在那里 它应该被存储。结构有 限制功能的比较 课程,因此如果结构不能提供 所需的功能,像 默认的构造,定义类。
  5. 如果有什么可以执行的任何 行动数据的其他 类型,它通常被定义为一个 类。对于结构与行动 不同类型的定义应该 如果你只能投一类型的 另一个。说你可以添加int 双因为你可以投int 一倍。
  6. 如果事情应该是无国籍,这是一类。
  7. 当你正犹豫不决,使用的基准类型。:-)

任何规则允许排除在特殊情况下,但不要尝试过优化。

p.s.我遇到了一些ASP.NET 开发人员2-3年的经验,谁不知道之间的差堆和堆。:-(我不会租用这样一个人如果我是个采访但并不是因为拳/拆箱可能是一个瓶颈中的任何ASP.NET 网站是我见过。

我认为c#中装箱的一个很好的例子出现在非泛型集合中,如 ArrayList

一个例子是当一个方法接受一个object参数并且必须传入一个值类型时。

以下是装箱/拆箱的一些例子

ArrayList ints = new ArrayList();
myInts.Add(1); // boxing
myInts.Add(2); // boxing

int myInt = (int)ints [0]; // unboxing

Console.Write("Value is {0}", myInt); // boxing

发生这种情况的一种情况是,例如,如果您有方法期望类型为object的参数,并且您正在传递其中一种基本类型,例如int。或者,如果将参数定义为int类型的“ref”。

代码

int x = 42;
Console.Writeline("The value of x is {0}", x );

实际上是盒子和拆箱,因为Writeline在内部进行了int投射。为了避免这种情况,你可以做到

int x = 42;
Console.Writeline("The value of x is {0}", x.ToString());

谨防微妙的错误!

您可以通过将自己的类型声明为struct来声明自己的值类型。想象一下,您声明了一个包含大量属性的ArrayList,然后将一些实例放在[]中。这当然是他们的盒子。现在通过readonly运算符引用一个,将其转换为类型并设置属性。您只需在副本上设置属性即可。 <=>中的那个仍未修改。

由于这个原因,值类型必须始终是不可变的,即使所有成员变量<=>,以便它们只能在构造函数中设置,并且没有任何可变类型作为成员。

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