Essentially, it means you're trying to evaluate the contents of the IEnumerable more than once. There's no way of telling if an IEnumerable is a list (where all the values have already been calculated, and you know how long it is up front), or a custom enumerable, such as an iterator calling "yield return" on an infinite number of items, or where the items are calculated on demand (in which case, the items in the enumerable might be different each time you loop over them).
Thank you for your answer. I see now that if I pick "Supress inspecition", I get the option to see why as you explained. But Isn't this always a posiblity with a Linq expression? Shouldn't it be the job of the creater of the IEnumerable to decide wheter the enumeration is expensive and not the user? Making ever user of an IEnumerable convert it to a list seems like a bad idea.
The issue is that the consumer of the enumerable isn't necessarily the owner of it, and so doesn't know if it's safe to enumerate multiple times. If it is safe, or if the method has a requirement to be able to enumerate multiple times, it might be more appropriate to accept an IList or IReadOnlyList as the parameter to the API. If not, then the API can choose to call ToList or ToArray (which might be a no-op, as LINQ optimises for existing interfaces), or it can choose to ignore ReSharper's warnings, disabling them via comments - but this is then an explicit choice, and you're not accidentally missing a potential issue.
>then the API can choose to call ToList or ToArray (which might be a no-op, as LINQ optimises for existing interfaces)
Just curious, when is .ToList() not allocating a new list instance and can the documentation for this behavior be read somewhere? (tried to find similar proof but in vain)
Looking at the source code, neither ToList nor ToArray is ever a no-op.
ToList always allocates a new List<T> instance.
ToArray uses the internal Buffer<T> class, which copies the sequence to an array. If the source implements ICollection<T>, it will allocate an array of the correct size and use the CopyTo method. Otherwise, it will copy the elements individually, doubling the size of the array each time it runs out of space. If the final array is not exactly the right size, it will then copy the elements to another array of the correct size before returning.
With this warning, you can actually hit alt+enter and select "Why is ReSharper showing me this?" and it'll take you to this page: https://confluence.jetbrains.com/display/ReSharper/Possible+multiple+enumeration+of+IEnumerable
Essentially, it means you're trying to evaluate the contents of the IEnumerable more than once. There's no way of telling if an IEnumerable is a list (where all the values have already been calculated, and you know how long it is up front), or a custom enumerable, such as an iterator calling "yield return" on an infinite number of items, or where the items are calculated on demand (in which case, the items in the enumerable might be different each time you loop over them).
Thank you for your answer. I see now that if I pick "Supress inspecition", I get the option to see why as you explained.
But Isn't this always a posiblity with a Linq expression? Shouldn't it be the job of the creater of the IEnumerable to decide wheter the enumeration is expensive and not the user? Making ever user of an IEnumerable convert it to a list seems like a bad idea.
The issue is that the consumer of the enumerable isn't necessarily the owner of it, and so doesn't know if it's safe to enumerate multiple times. If it is safe, or if the method has a requirement to be able to enumerate multiple times, it might be more appropriate to accept an IList or IReadOnlyList as the parameter to the API. If not, then the API can choose to call ToList or ToArray (which might be a no-op, as LINQ optimises for existing interfaces), or it can choose to ignore ReSharper's warnings, disabling them via comments - but this is then an explicit choice, and you're not accidentally missing a potential issue.
>then the API can choose to call ToList or ToArray (which might be a no-op, as LINQ optimises for existing interfaces)
Just curious, when is .ToList() not allocating a new list instance and can the documentation for this behavior be read somewhere? (tried to find similar proof but in vain)
According to the source code, ToList always allocates a new List<T>:
http://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs,833
Looking at the source code, neither ToList nor ToArray is ever a no-op.