Search code examples
c#performancelinqienumerable

To ToList() or not to ToList()?


Given an in memory (not LINQ to SQL) list of classes:

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

which I am grouping using a GroupBy() statement:

myItems.GroupBy(g => g.Ref)

and then immediately consuming in a foreach loop is there any difference in calling .ToList() on the "group" or should I just use an IEnumerable.

So full code examples:

With 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());
  }
}

or

Using 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());
  }
}

Is there any difference in the execution plan of these "under the hood"? Would either of these be more efficient or does it not really matter?

I am not using the groupedItems list after this.


Solution

  • Yes there is a difference and it can be significant.

    ToList() will iterate and append each iterated item into a new list. This has the effect of creating a temporary list which consumes memory.

    Sometimes you might want to take the memory penalty especially if you intend on iterating the list multiple times and the original list is not in memory.

    In your particular example using the ToList() you actually end up iterating twice - once to build the list and a second time in your foreach. Depending on the size of the list and your application this may or may not be a concern.