jotbek
jotbek

Reputation: 1499

Is it better to do ToList() before ToDictionary?

Is it worth to do the ToList() before doing the GroupBy() and ToDictionary() twice as in example below. Does the ToList() may maximize the performance when creating the dictionary? Without ToList() Resharper is yelling about possible multiple enumeration.

public void SomeMethod(IEnumerable<oldItem> oldItems)
{
    var collection = oldItems.Select(i => new item()).ToList();
    var dict1 = collection.ToDictionary(i => i.Key);
    var dict2 = collection
         .GroupBy(i => i.FieldA)
         .ToDictionary(g => g.Key, g => new Flags(g.ToArray));
}

Upvotes: 4

Views: 1718

Answers (4)

Anton&#237;n Lejsek
Anton&#237;n Lejsek

Reputation: 6103

I would state it simply - do not enumerate IEnumerable multiple times. Just do not do that. If you need to iterate over multiple times, you can define IList/IReadOnlyList interface. Btw. you can construct the second dictionary from values of the first in this case.

Upvotes: 0

Tim Schmelter
Tim Schmelter

Reputation: 460058

Is it better to do ToList before ToDictionary?

No, Enumerable.ToDictionary enumerates all items anyway so there is no benefit. The opposite is true, you need to fill another collection in a loop for no reason

Is it better to do ToList() before ToDictionary if i need multiple dictionaries?

Probably. It depends on the type of the sequence. It could be a database query that takes ages to execute. Without ToList you will execute it multiple times. But it could also be a collection or very cheap query. Resharper wants you to think about it.

There's another subtle difference which has nothing to do with performance. If you don't store the sequence in a collection(f.e with ToList) you could be in a deferred execution context(f.e. if oldItems is a database query). That means whenever you execute this query you will get the current result which could be different to the previous execution's result. That might be desired, you just have to keep that in mind.

Upvotes: 9

Gy&#246;rgy Kőszeg
Gy&#246;rgy Kőszeg

Reputation: 18013

Without the ToList your collection is a SelectEnumerator around the oldItems, which will be enumerated twice for both dict1 and dict2. This means that i => new item() will be called twice for each elements of oldItems.

Upvotes: 0

Mixxiphoid
Mixxiphoid

Reputation: 1034

Resharper warns you that the next item of the IEnumerable may be consumed twice when you intend only once. Putting the items in a list consumes the IEnumerable into a list. You can enumerate over a list as many times you want, where IEnumerable will yield the next item. collection may be consumed by the first usages, therefore the behaviour may be unexpected for the second use.

Upvotes: 1

Related Questions