ToList()的效率

Chr*_*ris 5 .net c#

与我合作的很多开发人员感觉更舒服List,而不是IEnumerable(例如).我想知道是否对ToList()过度使用有任何性能影响.例如,或者,将ToList()在订购后使用再次获取列表,即

private void ListThinger(List<T> input)
{
  input = input.OrderBy(s => s.Thing).ToList();
  foreach(var thing in input)
  {
      // do things
  }
}
Run Code Online (Sandbox Code Playgroud)

我的问题是:

  • ToList()方法效率如何?假设内容是POCO,它会创建一个新列表以及需要多少内存吗?如果它是值类型而不是POCO,这会改变吗?
  • 列表的大小是否会确定效率或列表的大小不确定成本ToList()
  • 如果列表被强制转换为a IEnumerable然后ToList()被调用,它是否会返回原始对象?

Ps我明白单独使用ToList不会破坏任何支持,但是我们正在构建一个高度并发的系统,这个系统目前受CPU限制,因此我正在寻找一些小胜利,当缩放时,它将会带来很大的改进

Gil*_*een 3

ToList() 方法的效率如何?假设内容是 POCO,它会创建一个新列表吗?需要多少内存?如果它是值类型而不是 POCO,这会改变吗?

ToList()方法通过创建一个新列表并用给定集合的项目填充它来具体化给定集合。Linq.ToList()执行

public static List<TSource> ToList<TSource>(this IEnumerable<TSource> source) {
    if (source == null) throw Error.ArgumentNull("source");
    return new List<TSource>(source);
}
Run Code Online (Sandbox Code Playgroud)

通过这样做,您将无法在需要时获得延迟执行的能力


列表的大小会决定效率还是列表的大小不会决定 ToList() 的成本?

当它调用List复制构造函数并创建一个新列表时,它将对每个项目起作用。所以它会运行O(n)- 这意味着列表的大小很重要。关于复制构造函数操作的MSDN文档:

初始化 List 类的新实例,该实例包含从指定集合复制的元素,并具有足够的容量来容纳复制的元素数量。

正如 @Jason 在下面的评论中提到的,复制构造函数很聪明并且高效,但是在不需要时执行它仍然是一个O(n)不必发生的操作


如果将列表强制转换为 IEnumerable,然后对其调用 ToList(),它会只返回原始对象吗?

不会。它将创建一个新列表,如上所示


至于你的示例代码:

input = input.OrderBy(s => s.Thing).ToList();
foreach(var thing in input)
{
   // do things
}
Run Code Online (Sandbox Code Playgroud)

当您获得一个物化列表(而不是可能在延迟执行中执行的IQueriable/ IEnumerable)时ToList,在添加之后添加 不会给您带来任何好处。

你可以看看这里,可能也会有帮助:When to use LINQ's .ToList() or .ToArray()