单个类类型的 C# 数组或列表

本文关键字:列表 数组 类型 单个类 | 更新日期: 2023-09-27 18:27:27

我有一个包含一些基本类型的类。(3x 浮点数,2x 整数(。

现在,我需要一个可以容纳此类的数百万个实例的集合。我不需要派生类型。所有元素都完全来自这个单一类。此外,元素的数量是固定的。在极少数情况下,我计划复制整个列表/数组并修改副本。最初的列表/数组应该是不可变的,因此我不需要与其他线程同步。

现在的问题是:

  • 我是否受益于数组而不是列表?
  • 我是否使用阵列节省内存?
  • 速度呢?

我读到C#中的List在内部也作为数组实现。

如果是C++,我知道数组将保存完整的对象。但我不确定 C# 如何处理这个问题。C# 数组是只保存对类实例的引用,还是保存完整的数据结构?

单个类类型的 C# 数组或列表

原来的列表/数组应该是不可变的,因此我不需要与其他线程同步。

您是否考虑过不可变的集合而不是T[]List<T> ImmutableArray<T>最有意义。可以使用ImmutableArray<T>.Builder以有效的方式创建集合。

  • 我是否受益于数组而不是列表?

如果你不需要改变元素的数量,你应该使用数组。它将让每个查看您的代码的人都清楚地知道您没有更改元素的数量。

  • 我是否使用阵列节省内存?

这取决于您如何创建List<T>。在内部,当您逐个添加元素以List<T>底层数组的大小会使用 2* 乘数进行更改:当没有足够的空间容纳新元素时,当前底层数组将被大小翻倍的新数组替换。所以是的,您可以直接使用 Array 节省内存,因为您不会分配任何不必要的内存。但是,您可以使用 List<T> 来实现相同的目的,方法是使用占用列表容量的构造函数创建它,或者在将所有元素添加到列表后调用TrimExcess方法。

  • 速度呢?

使用数组,你将保存将List<T>方法、属性和索引器属性调用转换为基础数组调用的逻辑。但是你不应该关心这个,它会不引人注意。

如果是C++,我知道数组将保存完整的对象。但我不确定 C# 如何处理这个问题。C# 数组是只保存对类实例的引用,还是保存完整的数据结构?

这要看情况。如果你将你的类型定义为引用类型(class(,数组和列表都将只保存对特定项目的引用。如果将其定义为值类型(struct(,数组将保存实际元素。

  1. 没有。内部列表只是普通数组,并且另外对List(不在数组中(中的元素进行计数器。你只会有更多的功能差。
  2. 如果您知道元素计数,并在列表初始化时设置它,那么您将不会节省任何内存。使用 List 使用的内存很少,虽然列表大小是固定的,但它不依赖于元素的数量。但是,如果您没有指定确切的列表大小,那么每次添加新元素时,内部数组的大小都会加倍,并且 List 元素的数量大于内部数组大小。
  3. 不。大多数情况下,它与使用纯数组相同。除了内部数组大小调整时间(但它不会太长,并且在 List 固定时不会发生(。

在C++数组和列表中,数组和列表并不总是将整个完整的对象存储在其中。它们可以只包含引用。在 .NET 语言中也是如此(即使对于托管C++也是如此(。值类型将按原样存储。引用类型将被存储...作为对对象的引用。