哪些值类型存储在(C#)通用集合中

确实,generics集合比值非类型的非generics集合表现更好。 (即List与ArrayList)。

但除了拳击拆箱步骤之外,为什么呢? 一旦添加到集合中,值类型对象存储在哪里? 在非generics集合中,它们将被装箱并存储在堆上,generics中有什么不同?

在generics中,例如List ,它们仍然存储在堆上。 区别在于,在内部, List生成一个整数数组,并且可以直接存储数字。 使用ArrayList,您最终会存储对盒装整数值的引用数组。

相关的实现细节是List的底层存储是T []。 因此对于List ,值将存储在int []中。 整数存储在连续的内存块中,从垃圾收集堆中分配。

使它如此快速的原因不仅仅是整数没有盒装,而是int []在CPU缓存中运行得非常好。 当您读取第一个元素时,您基本上可以免费获得下一个15,而无需读取慢速RAM或二级缓存。 这对于盒装int来说效果不是很好,因为它太大而且额外的引用可能具有较差的缓存局部性。 但是,垃圾收集器确实有助于通过压缩堆来消除成本。

ArrayList是对存储在堆中的对象的引用的本地数组。

引用类型的通用列表是对存储在堆中的对象的本地引用数组。

值类型的通用列表是这些值类型的本地数组。

内存有两个区域,大多数引用称为“堆栈”和“堆”。 大多数使用这些术语的人都不知道为什么。 (“堆栈”可能是一个堆栈,但堆几乎肯定不是堆)。 我更喜欢“Over Here”和“Over There”这两个词。 装箱时,值类型数据存储在“Over There”。 当存储在数组中时(可能在通用List中),值类型数据存储在“Over Here”中。 “在这里”更好。

除了装箱和拆箱之外,还有几个原因,包括内存缓存以及枚举它们执行作业的方式。 看看这篇文章,特别是评论 。

generics中的性能提升通常仅与generics使用的值类型相比,存储在非generics等价物中的值类型。

这是因为使用generics值类型不需要转换为对象并存储在堆上(盒装)。 实际上,它们可以保留在更高性能的堆栈上。

http://msdn.microsoft.com/en-us/library/ms172181.aspx