【问题标题】:What is more efficient: List<T>.Add() or System.Array.Resize()?什么更有效:List<T>.Add() 或 System.Array.Resize()?
【发布时间】:2011-01-18 04:07:20
【问题描述】:

我正在尝试确定何时使用 List&lt;T&gt;.Add() 与使用 Array.Resize() 方法更有效。

Array.Resize 的文档说它会复制整个数组,并将其放入一个新对象中。旧对象将不得不被丢弃。这个旧物体在哪里?在栈上还是堆上?

我不知道 List.Add() 是如何工作的。

有谁知道 List.Add 方法与静态 Array.Resize 方法的比较?

我对内存使用(和清理)感兴趣,以及 300 种值类型与 20,000 种值类型相比哪个更好。

对于它的价值,我计划在 .NET 的嵌入式风格之一上运行此代码。可能是.NET Gadgeteer

【问题讨论】:

  • 没有任何装箱问题。不要重新发明轮子。 List&lt;T&gt; 存在是有原因的;使用它!
  • 我有一种感觉 List 是超过 500 个对象的答案,但读完后我很好奇(搜索 500)msdn.microsoft.com/en-us/library/6sh2ey19.aspx
  • System.Array 是否存在装箱问题?
  • 您可能正在担心一些您不需要担心的事情。除非您有问题,否则使用 List 如果您非常清楚您的列表通常包含多少项目,您可以使用容量参数。如果您遇到性能问题 - 您可能可以在代码中做出比这更好的修复。
  • @makerofthings7 数组是“引用类型”——单元格是什么类型并不重要。它们具有仅通过访问运算符公开的基础支持。 “值类型”存在于堆栈中的概念在很大程度上是错误的,仅适用于某些情况(例如本地特定类型的变量和/或方法参数),并且是一种实现特性/细节。

标签: c# .net arrays generics .net-micro-framework


【解决方案1】:

您应该使用List&lt;T&gt;

使用Array.Resize 将强制您在每次添加项目时单独扩展数组,从而使您的代码大大变慢。 (因为数组不能有多余的容量)

List&lt;T&gt; 由一个阵列支持,但拥有用于放入项目的备用容量。
添加项目所需要做的就是在数组中设置一个元素并增加其内部size计数器。
当数组填满时,列表的容量会增加一倍,从而可以毫不费力地再次添加未来的项目。

【讨论】:

  • 我很好奇什么最适合 300 个对象,因为 MSDN 说 List 在大约 500 个对象上可以收回成本
  • 更进一步,我将创建许多包含 300 个对象的数组,因此了解这种优化可能是有益的,而不仅仅是学术性的。
  • 如果您确切知道需要多少项目,您可以在构造函数中设置List 的容量。这样,您将不需要任何调整大小。其性能将完全等同于数组。
  • 复制数组;旧副本由 GC 收集。
  • @JeremyThompson:在 List 上尝试 for。或致电ToArray()
【解决方案2】:

.NET Micro Framework 不支持泛型,因此我将使用数组,根据需要复制和销毁它。

我可能会将该性能与此处的 powertools 库中提到的展开链表进行比较: Any implementation of an Unrolled Linked List in C#?

【讨论】:

    【解决方案3】:

    .NET Micro Framework(尚)不支持泛型。您在动态集合方面受到限制。

    选择方法时要考虑的一件事是,微控制器上的托管代码非常非常慢。托管 .NET Micro Framework 对象中的许多操作实际上只是调用本机代码来完成工作。这要快得多。

    例如,比较在 for 循环中逐个元素复制数组元素与调用 Array.Copy() 本质上做相同的事情,但在本机代码中。

    在可能的情况下,使用这些原生扩展来获得更好的性能。还可以考虑查看 CodePlex 上的 MicroLinq project。有一个子项目专门用于 NETMF 上的增强集合(也可作为 NuGet package 获得)。该代码可免费获得并公开许可用于任何目的。 (完全披露:我是那个项目的开发者。)

    如果您可以避免分配一个大数组并跟踪保存真实数据的最大位置,这将是最快的,但需要在设计中投入更多的工作/思想,并花费时间构建很酷的东西。

    【讨论】:

      【解决方案4】:

      只有在频繁调整数组大小时(例如每次添加项目时),List 才会更快。但是,如果每隔几帧调整一次大小,List 和内置数组应该是等效的,也许数组更快。

      【讨论】:

        【解决方案5】:

        我在反编译后看到了 List 的实现,发现它使用 Array.Resize() 作为内部数组。但是它管理元素计数器并使用数组的长度作为容量,并在您调用 Add() 时使用一些额外的空间调整数组的大小。所以,我想你可以为你的情况制定比 List 更优化的分配策略。但是您必须手动管理元素计数器。此外,在访问数组元素时,您将摆脱索引器开销,因为 List 内的索引器只是请求内部数组元素的方法。如果只是瓶颈,我认为用手动调整大小的数组替换 List 是值得的。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-11-12
          • 1970-01-01
          • 1970-01-01
          • 2011-04-04
          • 2011-03-16
          相关资源
          最近更新 更多