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:
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
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.
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.
If you are sure you'll use groupedItems
only once, then using .ToList()
has a single advantage: if there is an exception (for example because your code is doing funny things for calculating .Ref
) during the grouping, the exception will be in the .ToList()
row instead of being inside the foreach
... I don't think it is a big advantage (and perhaps it is a disadvantage).
To clarify:
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";
}
}
}
Note that you have explicitly tagged this question as IEnumerable
, and in your example myItems
is a List<>
, so I won't discuss of the difference of doing ToList()
or not when you are reading data from a database through Entity Framework/Linq to SQL.
Is there any difference?
Yes, .ToList()
creates a new list from iterating the grouped collection:
The
ToList<TSource>(IEnumerable<TSource>)
method forces immediate query evaluation and returns a List that contains the query results.
Whether this is noticeable should be benchmarked by you.
If you only iterate the grouped collection once, the .ToList()
step is unnecessary and will be relatively slower than directly enumerating the GroupBy()
result.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With