C#List <T> .ToArray表现不好?

Geo*_*ge2 26 .net c# memory performance

我正在使用.Net 3.5(C#),我听说C#的性能List<T>.ToArray"糟糕",因为它为所有元素的内存副本形成了一个新的数组.真的吗?

Joe*_*Joe 51

不,那不是真的.性能很好,因为它所做的只是内存复制所有元素(*)以形成一个新数组.

当然,这取决于你所定义的"好"或"坏"表现.

(*)引用类型的引用,值类型的值.

编辑

在回复您的评论时,使用Reflector是检查实现的好方法(见下文).或者只考虑几分钟如何实现它,并相信微软的工程师不会提出更糟糕的解决方案.

public T[] ToArray()
{
    T[] destinationArray = new T[this._size];
    Array.Copy(this._items, 0, destinationArray, 0, this._size);
    return destinationArray;
}
Run Code Online (Sandbox Code Playgroud)

当然,"好"或"坏"表现只相对于某些选择具有意义.如果在您的具体情况下,有一种替代技术可以更快地实现您的目标,那么您可以将性能视为"糟糕".如果没有这样的替代方案,那么表现就是"好"(或"足够好").

编辑2

回应评论:"没有重建物体?" :

没有重建参考类型.对于值类型,复制值,可以将其粗略地描述为重建.

  • 谢谢乔,你的回答太酷了!您是否有任何相关文件需要进一步讨论或进一步证明索赔 - "所有这些都是内存复制所有元素(*)以形成新阵列."? (2认同)

Sor*_*tis 21

调用ToArray的原因()

  • 如果不想修改返回的值,则将其作为数组返回会使事实更加清晰.
  • 如果期望调用者对数据执行许多非顺序访问,则可以通过List <>对数组执行性能优势.
  • 如果您知道需要将返回的值传递给需要数组的第三方函数.
  • 与需要使用.NET版本1或1.1的调用函数的兼容性.这些版本没有List <>类型(或者任何泛型类型).

没有调用ToArray的原因()

  • 如果调用者确实需要添加或删除元素,则绝对需要List <>.
  • 不一定能保证性能优势,特别是如果调用者以顺序方式访问数据.还有从List <>转换为数组的额外步骤,这需要处理时间.
  • 调用者总是可以将列表转换为数组.

取自这里

  • 这是我们能给出的唯一答案:正确性总是胜过性能.你不是那些仍然正确的最高效的东西.应用程序就是你不要调用.ToArray(),除非你必须这样做. (4认同)
  • "......对于List <>,数组可以带来性能优势." - 有什么证据吗?对我来说听起来像是一个神话. (4认同)
  • 返回数组并不表示无法修改它.BCL充满了返回数组的方法,接收者可以很自由地修改数组. (3认同)
  • 好的推荐,但不能直接回答我的问题?你对我的问题的答案是什么? (2认同)
  • 2.0 之前的 .NET 框架具有非泛型集合以及数组。 (2认同)

chr*_*166 5

是的,确实可以对所有元素进行内存复制。这是性能问题吗?这取决于您的性能要求。

List内部包含一个数组来保存所有元素。如果容量不足以容纳列表,则阵列会增加。无论何时,列表都会将所有元素复制到新数组中。这种情况一直在发生,对于大多数人而言,这并不是性能问题。

例如,具有默认构造函数的列表以容量16开始,当您.Add()使用第17个元素时,它将创建一个大小为32的新数组,复制16个旧值并添加第17个值。

大小差异也是ToArray()返回新数组实例而不传递私有引用的原因。