4

Visual Studio gives me the warning "Warning: Possible multiple enumerations" on an IEnumerable. And then I add ToList() to it. But I started to wonder why it's a bad practice.

So why is it bad to enumerate multiple times?

Roy Berris
  • 1,502
  • 1
  • 17
  • 40
  • 2
    Some sequences CANNOT be enumerated multiple times, or will give you different results when enumerated multiple times. – Matthew Watson Oct 19 '21 at 09:34
  • 1
    Just to add to @MatthewWatson you might have a sequence pulled from a database or web-service or some other relatively "slow" shared resource. Enumerating multiple times means hitting the resource multiple times which will either slow down your program, or slow down the shared resource, or both. – RB. Oct 19 '21 at 09:35
  • Explained very good here: https://www.jetbrains.com/help/resharper/PossibleMultipleEnumeration.html – RvdK Oct 19 '21 at 09:35
  • Imagine if you get the enumeration from a remote resource which is bitcoin prices, if you enumerate them again they will be different. If you are relying on that being deterministic, you just entered fail town – TheGeneral Oct 19 '21 at 09:36
  • I would suggest to use ````ToArray()```` instead of ````ToList()```` but still treat the variable as ````IEnumerable````. Array is less expensive. – cly Oct 19 '21 at 09:37
  • 1
    @cly negligable – Ermiya Eskandary Oct 19 '21 at 09:44
  • 1
    @ErmiyaEskandary quick empirical tests on 10m items show you have right, despite ToList's timing values are almost twice as big than ToArray's ones the results are still in 10s of ms range so negligable. There are topics on this subject here like this old one: https://stackoverflow.com/questions/454916/performance-of-arrays-vs-lists is somebody interested. – cly Oct 20 '21 at 22:56

3 Answers3

5

“Possible multiple enumeration of IEnumerable“ is a resharper warning. If you enumerate an enumerable more than once, ReSharper will detect this and warn you about it. Although this warning may seem pointless at first, there are two good reasons to pay attention to it:

  1. Enumerating an enumerable can be very expensive. For example, an enumerable might be backed by a database. Re-enumerating may force you to wait another network round trip. You don’t want to pay that cost twice.

  2. Performance problems caused by multiple enumerations compound on themselves.

Please check out this article to get more info about this warning : http://twistedoakstudios.com/blog/Post7694_achieving-exponential-slowdown-by-enumerating-twice

Ran Turner
  • 14,906
  • 5
  • 47
  • 53
  • 4
    There is a third and more important reason; enumerations *aren't guaranteed to be repeatable* - it could return completely different data, or not be able to repeat at all; consider, for example, an enumerable that is pulling from external data over an open `Socket` (where it doesn't control the other end), or where data is coming from some kind of RNG (in particular a CRNG, or a PRNG where the seed isn't part of the enumerator source) – Marc Gravell Oct 19 '21 at 10:07
2

You're essentially looping over the collection twice in your code, which is why you're getting that ReSharper warning.

When using an IEnumerable returned by a database call, for example, this means getting the data twice, slowing down your application & resulting in unnecessary database load. Why get the data twice?

If using an enumerable in memory, enumerating multiple times over the collection may also be very costly depending on the size of the collection.

Using .ToList() resolves the error because it forces the enumeration at the point of variable initialization by converting the IEnumerable to a list (you can also force this by casting the IEnumerable to an array using ToArray).

The data inside IEnumerable collections may also change between enumerations so it's best to force enumeration at the point where you need the data to stay put (the items in the enumerable might be different each time you loop over them).

By JetBrains themselves: Code Inspection: Possible multiple enumeration of IEnumerable

Ermiya Eskandary
  • 15,323
  • 3
  • 31
  • 44
1

Enumeration of items in an IEnumerable may be costly depending on the implementation type. Enumerating several times over a List in memory does not make much difference. If the IEnumerable is a database selector it may be faster to iterate over it once using toList() and then iterate over the List

Bennik2000
  • 1,112
  • 11
  • 25