对收藏感到困惑,我需要简要介绍所有收藏的要点。
数组可以称为集合吗?常识说是的,因为这是元素的集合,但在尖锐的地方有数组,有集合,还有泛型。并不是所有的事情都对他们很清楚。
- 我们知道集合是泛型之前的通用元素分组机制的旧版本。这些是 ArrayList、Stack、Queue、Hashtable
您添加的所有内容都保存为object,这会导致装箱和拆箱,如果变量是值类型,例如 int,那么我们复制它 - 结果我们得到两个变量。
问题 - 这仅适用于集合,还是简单数组的工作方式相同?
分配单元格值时,int 数组是否进行装箱和拆箱?我们是在分配数组单元格值时复制 int 值,还是以其他方式工作?
- Richter 写道,泛型的优点之一是不需要打包——拆包,因为。泛型是强类型的,不会与对象相互转换,而是以这种方式存储的。
但是它们存储在堆上吗?如果原始类型是值类型,我们还有值复制吗?
引用类型对所有集合的工作方式是否相同——它们不会被复制,只是将对实例的引用存储在它们的单元格中?数组、集合和泛型的主要区别在处理值类型时是否准确体现?
是否所有集合和数组都引用类型,它们的所有单元格及其所有内容是否都存储在堆上?
收藏的底层是什么?ArrayList 或 List 是如何在内部实现的?我读到 Dictionary 在引擎盖下有一个 Hashtable,它只是使用键的哈希值来查找,但是 Hashtable 本身是如何工作的呢?里面有数组吗?
这些问题重叠并且有点令人困惑,因为我将我所知道的关于集合的所有内容都放入其中。貌似我用过,但一切都散了,现在读了里希特,总体上是一头雾水。
如果有关于比较所有集合及其内部实现的简短摘要,我将不胜感激。
泛型是一种概括。
集合可以是通用的或非通用的。
数组最初具有特殊的地位,事实上,它总是被泛化的。
您似乎害怕复制值。但这并不可怕,因为习惯上使值类型变小并且复制它们与复制引用类型指针相当。
既然你读过里希特,你就已经为痛苦和屈辱做好了心理准备……在现代 dotnet 实现中,可以在堆栈上创建引用类型!但这是运行时优化,我们不应该特别担心。
泛型和非泛型集合之间的区别不仅限于值类型的处理。
object使用泛型,在使用引用类型时不需要强制转换(cast) 。也就是说,使用它们更容易、更安全。我将给出一个图表,说明重要类型如何存储在类型的数组和泛型集合中
List<T>:这就是它们将如何存储在非通用集合中的方式:
在集合本身 - 链接。并且打包(装箱)的值分散在堆上。
不必要。例如,这里的ImmutableArray Struct - 如您所见,这是一个值类型。里面有什么不重要。
没有人也没有什么能阻止您创建一个在字段中存储一组值的集合结构。实现索引器、枚举器——集合的所有属性。在这种情况下,不使用堆。
stackalloc是在堆栈上创建数组的标准方法。
如果您从哲学意义上广泛地看待这个问题,那么答案是:任何事情!
可能在堆栈或堆中分配了一块内存,或者可能使用任何协议直接访问文件、数据库或服务。
您可以在Wikipedia上阅读有关 Hash 表的实现(有一次我被它的内部结构惊呆了,一开始我被它的复杂性所震撼,最后我被它的美丽所吸引)。
也可以查看那里的其他数据结构。如果您会说英语,请切换到它。
这是部分答案。
从技术上讲,数组不是 C# 中的集合,因为它们不是 System.Collections 的一部分。正如您所写,常识使我们通常将数组和集合视为包含值集的数据结构。类似于我们在数学中所说的“集合”。最主要的是数组在打包/解包方面没有问题。
我们知道,集合构成了许多用于在 C# 中存储数据的结构的基础。这些集合是专门的或扩展的,以提供一些额外的功能——例如,堆栈、队列、字典、哈希表。
原始的非泛型版本使用对象。对于值类型,它们意味着使用装箱/拆包机制。检查这篇文章:“不应使用非泛型集合” https://github.com/dotnet/platform-compat/blob/master/docs/DE0006.md
泛型不仅仅是集合的一个特性。它们是 C# 的一个重要特性。对于集合,它们可以在不将其包装为对象的情况下存储值。
更多信息 - 可能太多了 - 在这里:https ://mihai-albert.com/2020/02/10/boxing-performance-in-c-versus-generics/