C# - 是否可以装箱?

ric*_*ice 12 c# boxing memory-management

Boxing将值类型转换为对象类型.或者正如MSDN所说,装箱是一种"将结构包装在托管堆上的引用类型对象中的操作".

但是如果你试着通过查看IL代码来深入研究,那么你只能看到神奇的单词"box".

猜测,我猜运行时有一些基于泛型的秘密类,就像Box<T>一个public T Value属性一样,而装箱的int看起来像:

int i = 5;
Box<int> box = new Box<int>;
box.Value = 5;
Run Code Online (Sandbox Code Playgroud)

拆箱int会便宜得多: return box.Value;

不幸的是,我的性能饥渴的服务器应用程序做了相当多的拳击,特别是小数.更糟糕的是,这些盒子是短暂的,这使我怀疑我支付了两次,一次用于装箱,然后再用于垃圾收集箱完成之后.

如果我自己解释这个内存,我会考虑在这里使用一个对象池.但由于实际的对象创建隐藏在IL中的魔术词后面,我有哪些选择?

我的具体问题:

  • 是否存在一种诱导运行时从池中取出盒子而不是实例化它们的现有机制?
  • 拳击期间创建的实例的类型是什么?是否可以手动控制装箱过程,但仍然可以与拆箱兼容?

如果最后一个问题看起来很奇怪,我的意思是我可以创建我自己的Box<T>DecimalBox类,汇集它,并手动打开/取消框.但是我不想去修改代码中消耗盒装值的各个地方(也就是unbox它).

Eri*_*ert 10

推测,我猜运行时有一些基于泛型的秘密类

你的推测几乎是正确的.从逻辑上讲,你可以认为一个盒子是一个神奇的Box<T>类型,其行为与你描述的一样(带有更多的魔法;例如,可空值类型框的方式有点不寻常.)作为一个实际的实现细节,运行时不使用泛型类型.拳击存在于CLR v1中,这是在将泛型类型添加到类型系统之前.

我的性能饥渴的服务器应用程序做了相当多的拳击,特别是小数.

如果你这样做会伤害然后停止这样做.而不是试图使拳击更便宜,而不是首先停止做.你为什么拳击小数?

更糟糕的是,这些盒子是短暂的,这使我怀疑我支付了两次,一次用于装箱,然后再用于垃圾收集箱完成之后.

昙花一现比长寿更好 ; 与短命堆中的对象你付出收集它们一次,然后他们就死定了.对于长期存在的堆对象,当对象继续存活时,您会一次又一次地支付该成本.

当然,您可能担心短期物品的成本并不是收集本身的成本.相反,这是收集压力 ; 分配的更短期对象等于更频繁的垃圾收集.

分配成本非常低.在GC堆上移动指针,将小数复制到该位置,完成.

如果我自己解释这个内存,我会考虑在这里使用一个对象池.

对; 您需要支付更多收集长寿命物品的费用,但由于产生的收集压力较小,因此总收入较少.这可能是一场胜利.

是否存在一种诱导运行时从池中取出盒子而不是实例化它们的现有机制?

不.

拳击期间创建的实例的类型是什么?是否可以手动控制装箱过程,但仍然可以与拆箱兼容?

盒子的类型是盒子的类型.只需通过调用GetType来询问它; 它会告诉你.盒子很神奇; 它们是它们所包含的东西的类型.

就像我之前说过的,而不是试图让拳击更便宜,只是不要在第一时间做.