ToList()或不ToList()?

时间:2015-05-01 10:06:22

标签: c# performance linq ienumerable tolist

给出 in memory (不是LINQ to SQL)类列表:

List<MyClass> myItems = /*lots and lots of items*/;

我使用GroupBy()语句对其进行分组:

myItems.GroupBy(g => g.Ref)

然后立即在foreach循环中消费,在&#34;组&#34;上调用.ToList()是否有任何区别或者我应该使用IEnumerable

完整的代码示例:

使用ToList()

List<List<MyClass>> groupedItemsA = new List<List<MyClass>>();
List<List<MyClass>> groupedItemsB = new List<List<MyClass>>();

List<MyClass> myItems = /*lots and lots of items*/;
List<IGrouping<string, MyClass>> groupedItems = myItems.GroupBy(g => g.Ref).ToList();
foreach(IGrouping<string, MyClass> item in groupedItems)
{
  if (/*check something*/)
  {
     groupedItemsA.Add(item.ToList());
  }
  else
  {
    groupedItemsB.Add(item.ToList());
  }
}

使用IEnumerable

List<List<MyClass>> groupedItemsA = new List<List<MyClass>>();
List<List<MyClass>> groupedItemsB = new List<List<MyClass>>();


List<MyClass> myItems = /*lots and lots of items*/;
IEnumerable<IGrouping<string, MyClass>> groupedItems = myItems.GroupBy(g => g.Ref);
foreach(IGrouping<string, MyClass> item in groupedItems)
{
  if (/*check something*/)
  {
     groupedItemsA.Add(item.ToList());
  }
  else
  {
    groupedItemsB.Add(item.ToList());
  }
}

这些&#34;引擎盖的执行计划是否有任何不同?#34;?这些中的任何一个会更有效还是不重要?

此后我使用groupedItems列表

4 个答案:

答案 0 :(得分:5)

是的,有区别,可能很重要。

ToList()将迭代并将每个迭代项追加到新列表中。这具有创建消耗内存的临时列表的效果。

有时候你可能想要记忆惩罚,特别是如果你打算多次迭代列表并且原始列表不在内存中。

在您使用ToList()的特定示例中,您实际上最终会迭代两次 - 一次构建列表,第二次使用foreach。根据列表的大小和您的应用程序,这可能是也可能不是问题。

答案 1 :(得分:2)

如果您确定,您将仅使用groupedItems 一次,那么使用.ToList()有一个优势:如果有例外(例如,因为你的代码在分组过程中做了有趣的事情来计算.Ref),异常将在.ToList()行而不是在foreach内...我不喜欢认为这是一个很大的优势(也许这是一个缺点)。

澄清:

public class MyClass
{
    public string Ref
    {
        get
        {
            // sometimes I like to throw an exception!
            if (DateTime.Now.Ticks % 10 == 0) throw new Exception();

            return "Foo";
        }
    }
}

请注意,您已明确将此问题标记为IEnumerable,并且在您的示例中myItemsList<>,因此我不会讨论执行ToList()的区别当您通过Entity Framework / Linq to SQL从数据库读取数据时,是否存在。

答案 2 :(得分:1)

  

有什么不同吗?

是的,.ToList()通过迭代分组集合创建一个新列表:

  

The ToList<TSource>(IEnumerable<TSource>) method forces immediate query evaluation and returns a List that contains the query results

这是否明显应该由您进行基准测试。

如果只迭代分组集合一次,则.ToList()步骤是不必要的,并且比直接枚举GroupBy()结果要慢一些。

答案 3 :(得分:0)

如果您在每次枚举时使用UIAlertView而不是IEnumerable,则List()表达式将根据您的GroupBy列表进行重新评估。

这意味着如果您向myItems添加另一个项目然后枚举它,该项目将包含在myItems表达式中。

当您致电GroupBy时,您会创建一个新列表,ToList的任何更改都不会包含在myItems中。