用例在C#中装箱值类型?

fel*_*eon 10 c# boxing value-type reference-type cts

在某些情况下,需要将值类型的实例视为引用类型的实例.对于这种情况,可以通过名为boxing的过程将值类型实例转换为引用类型实例.当盒式化值类型实例时,将在堆上分配存储,并将实例的值复制到该空间中.对此存储的引用放在堆栈上.盒装值是一个对象,一个包含值类型实例内容的引用类型.

了解.NET的通用类型系统

维基百科中有一个Java的例子.但是在C#中,有哪些情况需要打包一个值类型?或者更好/类似的问题是,为什么人们想要在堆上(盒装)而不是堆栈上存储值类型?

Ree*_*sey 14

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

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

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


Ran*_*pho 13

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

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

  • 非常的.然而,反思是你想要限制的"我绝对不能做任何其他方式"的情况,所以我认为我的第一句话很好. (8认同)
  • 反射仍然会强制你使用box/unbox值,并且非常有价值...... (4认同)

LBu*_*kin 9

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

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

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

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


Bog*_*_Ch 5

我会推荐你​​2篇Eric Lippert的好文章

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%的应用程序中,开发人员不应该关心为什么Value类型在堆栈中而不在堆中,以及我们可以在这里获得什么样的性能.Juts考虑到非常简单的规则:

  1. 在没有必要时避免装箱/拆箱,使用泛型集合.大多数问题不是在您定义自己的类型时发生的,而是在您正确使用现有类型时(由Microsoft或您的同事定义)
  2. 使您的价值类型变得简单.如果你需要一个包含10-20个字段的结构,我想你最好创建一个类.想象一下,每当你偶尔通过值传递一个函数时,所有这些字段都会被复制......
  3. 我认为在其中包含引用类型字段的值类型并不是非常有用.与带有String和对象字段的struct一样.
  4. 根据所需功能定义所需类型,而不是存储位置.与类相比,结构具有有限的功能,因此如果struct无法提供所需的功能,如默认构造函数,则定义类.
  5. 如果某些东西可以对其他类型的数据执行任何操作,则通常将其定义为类.对于结构体,只有在可以将一种类型转换为另一种类型时,才应定义具有不同类型的操作.假设您可以将int添加到double,因为您可以将int转换为double.
  6. 如果某事应该是无国籍的,那就是一个阶级.
  7. 当您犹豫时,请使用引用类型.:-)

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

ps我遇到了一些具有2 - 3年经验的ASP.NET开发人员,他们不知道堆栈和堆之间的区别.:-(如果我是面试官,我不会聘请这样的人,但不是因为拳击/拆箱可能是我见过的任何ASP.NET网站的瓶颈.