Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resharper: Possible Multiple Enumeration of IEnumerable

I'm using the new Resharper version 6. In several places in my code it has underlined some text and warned me that there may be a Possible multiple enumeration of IEnumerable.

I understand what this means, and have taken the advice where appropriate, but in some cases I'm not sure it's actually a big deal.

Like in the following code:

var properties = Context.ObjectStateManager.GetObjectStateEntry(this).GetModifiedProperties(); if (properties.Contains("Property1") || properties.Contains("Property2") || properties.Contains("Property3")) {     ... } 

It's underlining each mention of properties on the second line, warning that I am enumerating over this IEnumerable multiple times.

If I add .ToList() to the end of line 1 (turning properties from a IEnumerable<string> to a List<string>), the warnings go away.

But surely, if I convert it to a List, then it will enumerate over the entire IEnumerable to build the List in the first place, and then enumerate over the List as required to find the properties (i.e. 1 full enumeration, and 3 partial enumerations). Whereas in my original code, it is only doing the 3 partial enumerations.

Am I wrong? What is the best method here?

like image 399
Ross Avatar asked Jul 06 '11 08:07

Ross


People also ask

How do you fix multiple enumeration of IEnumerable?

If the underlying type of the IEnumerable collection is an iterator-based implementation generated by LINQ methods like Select or yield in C# or yield statement in Visual Basic, you can fix the violation by converting and caching the collection to another type.

What does possible multiple enumeration mean?

Deferred Danger. One of the many useful warnings in ReSharper is “Possible multiple enumeration of IEnumerable“. If you enumerate an enumerable more than once, ReSharper detects that and warns you about it. Although this warning may seem pointless at first, there are two good reasons to pay attention to it.

How do you fix multiple enumerations?

This kind of problem can be easily fixed — force the enumeration at the point of variable initialization by converting the sequence to an array or a list, for example: List<string> names = GetNames().

Why is multiple enumerations bad?

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 Answers

I don't know exactly what your properties really is here - but if it's essentially representing an unmaterialized database query, then your if statement will perform three queries.

I suspect it would be better to do:

string[] propertiesToFind = { "Property1", "Property2", "Property3" }; if (properties.Any(x => propertiesToFind.Contains(x)) {      ... } 

That will logically only iterate over the sequence once - and if there's a database query involved, it may well be able to just use a SQL "IN" clause to do it all in the database in a single query.

like image 90
Jon Skeet Avatar answered Sep 18 '22 15:09

Jon Skeet


If you invoke Contains() on a IEnumerable, it will invoke the extension method which will just iterate through the items in order to find it. IList has real implementation for Contains() that probably are more efficient than a regular iteration through the values (it might have a search tree with hashes?), hence it doesn't warn with IList.

Since the extension method will only be aware that it's an IEnumerable, it probably can not utilize any built-in methods for Contains() even though it would be possible in theory to identify known types and cast them accordingly in order to utilize them.

like image 32
jishi Avatar answered Sep 22 '22 15:09

jishi