有情况下,当需要被处理的作为基准的类型的实例的值类型的实例。 对于这样的情况下,值类型实例可以通过一个称为装箱过程被转换成一个参考类型实例。 当值类型的实例是盒装,存储在堆上分配和实例的值复制到该空间。 此存储的引用被放置在堆栈中。 装箱值是一个对象,包含值类型实例的内容的引用类型。
了解.NET的通用类型系统
在维基百科有面向Java的例子。 但在C#中,有一些什么情况下,人们必须框的值类型? 或者会更好/类似的问题是,为什么一个要存储在堆上值类型(盒装),而不是在堆栈上?
有情况下,当需要被处理的作为基准的类型的实例的值类型的实例。 对于这样的情况下,值类型实例可以通过一个称为装箱过程被转换成一个参考类型实例。 当值类型的实例是盒装,存储在堆上分配和实例的值复制到该空间。 此存储的引用被放置在堆栈中。 装箱值是一个对象,包含值类型实例的内容的引用类型。
了解.NET的通用类型系统
在维基百科有面向Java的例子。 但在C#中,有一些什么情况下,人们必须框的值类型? 或者会更好/类似的问题是,为什么一个要存储在堆上值类型(盒装),而不是在堆栈上?
在一般情况下,你通常会希望避免你的拳击值类型。
不过,也有罕见的occurances这个地方是非常有用的。 如果您需要针对1.1框架,例如,您将无法访问泛型集合。 任何使用.NET 1.1藏品需要治疗你的价值类型为一个System.Object,这会导致装箱/拆箱。
还有这是在.NET 2.0 +有用的情况。 你想利用的事实,即所有类型,包括值类型,可直接视为一个对象的优势任何时候,你可能需要使用装箱/拆箱。 这有时可能得心应手,因为它可以让您保存在集合中任何类型的(通过使用对象,而不是T IN泛型集合),但在一般情况下,最好是避免这种情况,因为你失去的类型安全。 其中拳击频繁发生,虽然一个情况,就是当你使用反思 - 许多反射调用的值类型工作时,将需要装箱/拆箱,因为该类型是事先不知道。
有几乎从来没有一个很好的理由故意框的值类型。 几乎总是框的值类型的原因是将其存储在某些集合,不是类型察觉。 旧的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)更有效的是类型不可知。 这增加了一个理由使用通用集合,像List<T>
或Dictionary<T,K>
过ArrayList
或Hashtable
。
我建议你埃里克利珀的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%的应用程序开发人员不应该关心为什么值类型是堆栈,而不是在堆,我们可以有什么样的性能在这里。 伸出心目中非常简单的规则:
任何规则允许排除在特殊情况下,但不要试图过度优化。
PS我遇到了一些ASP.NET开发人员用2-3年的经验,谁不知道堆和栈之间的差异。 :-(我不会雇用这样的人,如果我是面试官,但不是因为装箱/拆箱可以在任何ASP.NET网站是一个瓶颈我见过。
我认为在非泛型集合等发生在C#中拳击的一个很好的例子ArrayList中 。
一个例子是当一个方法接受一个对象参数和值的类型必须传入。
下面是装箱/拆箱的一些例子
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
一当这种情况发生的情况是,例如,如果你有方法期望类型的对象的参数,以及要传递的基本类型之一,诠释例如。 或者,如果你定义的参数为int类型的“裁判”。
代码
int x = 42;
Console.Writeline("The value of x is {0}", x );
实际上箱和unboxes因为Writeline
做的int
投中。 为了避免这种情况,你可以做
int x = 42;
Console.Writeline("The value of x is {0}", x.ToString());
谨防微妙的错误的!
您可以通过声明自己的类型声明自己的值类型struct
。 想象一下,你声明一个struct
,有很多的属性,然后把某些情况下内部ArrayList
。 这个盒子他们当然。 现在参考一个通过[]
操作者,它铸造类型,并设置一个属性。 您只需设置一个副本的属性。 在一个ArrayList
仍然不变。
为此,值类型必须始终是不变的,即让所有的成员变量readonly
,这样它们只能在构造函数中进行设置,并没有任何可变类型的成员。