用例为拳击在C#中的值类型?(Use cases for boxing a value type i

2019-07-29 03:22发布

有情况下,当需要被处理的作为基准的类型的实例的值类型的实例。 对于这样的情况下,值类型实例可以通过一个称为装箱过程被转换成一个参考类型实例。 当值类型的实例是盒装,存储在堆上分配和实例的值复制到该空间。 此存储的引用被放置在堆栈中。 装箱值是一个对象,包含值类型实例的内容的引用类型。

了解.NET的通用类型系统

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

Answer 1:

在一般情况下,你通常会希望避免你的拳击值类型。

不过,也有罕见的occurances这个地方是非常有用的。 如果您需要针对1.1框架,例如,您将无法访问泛型集合。 任何使用.NET 1.1藏品需要治疗你的价值类型为一个System.Object,这会导致装箱/拆箱。

还有这是在.NET 2.0 +有用的情况。 你想利用的事实,即所有类型,包括值类型,可直接视为一个对象的优势任何时候,你可能需要使用装箱/拆箱。 这有时可能得心应手,因为它可以让您保存在集合中任何类型的(通过使用对象,而不是T IN泛型集合),但在一般情况下,最好是避免这种情况,因为你失去的类型安全。 其中拳击频繁发生,虽然一个情况,就是当你使用反思 - 许多反射调用的值类型工作时,将需要装箱/拆箱,因为该类型是事先不知道。



Answer 2:

有几乎从来没有一个很好的理由故意框的值类型。 几乎总是框的值类型的原因是将其存储在某些集合,不是类型察觉。 旧的ArrayList ,例如,是一个对象,它是引用类型的集合。 收集,说,整数的唯一方法,就是它们装箱为对象,并通过他们向ArrayList中。

现在,我们有泛型集合,所以这是不成问题的。



Answer 3:

拳击一般,当他们不得不在.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>ArrayListHashtable



Answer 4:

我建议你埃里克利珀的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. 避免装箱/拆箱的时候没有必要的,使用泛型集合。 当你定义自己的类型不发生大多数问题,但是当你使用现有各类inproperly(Microsoft或您的同事中定义)
  2. 让你的价值类型的简单。 如果你需要有10-20场一个结构,我想you'ld更好地创建一个类。 试想一下,所有的字段将每次被复制时,你偶尔按值传递的功能...
  3. 我不认为这是有值类型里面引用类型字段非常有用的。 像字符串和对象字段结构。
  4. 定义你需要根据什么类型所需的功能,而不是它应该被保存。 结构限制了比较类的功能,因此,如果结构不能提供所需的功能,像默认的构造函数,定义类。
  5. 如果有什么可以执行与其他类型的数据的任何行为,它通常被定义为一类。 对于不同类型的结构的操作应该被定义只有当你可以投一个类型到另一个。 假设你可以添加INT翻一番,因为你可以投INT翻番。
  6. 如果事情应该是无状态的,它是一个类。
  7. 当你犹豫,使用引用类型。 :-)

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

PS我遇到了一些ASP.NET开发人员用2-3年的经验,谁不知道堆和栈之间的差异。 :-(我不会雇用这样的人,如果我是面试官,但不是因为装箱/拆箱可以在任何ASP.NET网站是一个瓶颈我见过。



Answer 5:

我认为在非泛型集合等发生在C#中拳击的一个很好的例子ArrayList中 。



Answer 6:

一个例子是当一个方法接受一个对象参数和值的类型必须传入。



Answer 7:

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

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


Answer 8:

一当这种情况发生的情况是,例如,如果你有方法期望类型的对象的参数,以及要传递的基本类型之一,诠释例如。 或者,如果你定义的参数为int类型的“裁判”。



Answer 9:

代码

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 ,这样它们只能在构造函数中进行设置,并没有任何可变类型的成员。



文章来源: Use cases for boxing a value type in C#?