Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple enumeration of IEnumerable

I know IEnumerable has been discussed several times here but I couldn't find the answer to my specific question so I'm bringing it up as a new question.

Consider the following piece of code:

    static void Main(string[] args)
    {

        List<string> testList = new List<string> {"Test", "Test1", "Test1"};
        IEnumerable<string> filtered = testList.Where(x => x == "Test1");

        DoSomeWork(filtered);
        DoSomeMoreWork(filtered);
    }

    public static void DoSomeWork(IEnumerable<string> items)
    {
        foreach (var item in items)
        {
            Console.WriteLine("do some work");
        }
    }

    public static void DoSomeMoreWork(IEnumerable<string> items)
    {
        foreach (var item in items)
        {
            Console.WriteLine("do some more work");
        }
    }

Am I right, that this causes not only the two items in "filtered" to iterate two times but actually the items in "testList"? So, considering that "testList" was a big list with 10000 items and "filtered" reduces it to 10 items, it would be more clever to make "filtered" a list (aka use var and just append ToList() at the end)

EDIT: That's the most embarrassing question I ever asked here. I knew it would be bad to iterate an IQueryable for example because this would result in fetching the data twice from the DB. However I wasn't exactly sure about in memory lists. I would delete the question if I could ;-)

like image 642
Christoph Avatar asked Oct 20 '11 07:10

Christoph


People also ask

What is possible multiple enumeration of IEnumerable?

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.

Why is Possible multiple enumeration bad?

If the enumeration operation itself is expensive, for example, a query into a database, multiple enumerations would be harmful to the performance of the program. If the enumeration operation has side effects, multiple enumerations might result in bugs.

What is IEnumerable C#?

IEnumerable in C# is an interface that defines one method, GetEnumerator which returns an IEnumerator interface. This allows readonly access to a collection then a collection that implements IEnumerable can be used with a for-each statement.


2 Answers

The big list will be reiterated twice. To check that this really happens change your query to:

List<string> testList = new List<string> { "Test", "Test1", "Test1" };
IEnumerable<string> filtered = from t in testList
                               where t == "Test1"
                               select t;

If you then set a breakpoint on the 'where t == "Test1" part, you will see that the debugger hits this line for both the iterations.

like image 86
Wouter de Kort Avatar answered Sep 30 '22 14:09

Wouter de Kort


The big list will be reiterated twice. if you don't want it, you can "materialize" the restriction.

var filtered = testList.Where(x => x == "Test1").ToList();

And there are many answers that tell you this. You should have searched better :-)

like image 20
xanatos Avatar answered Sep 29 '22 14:09

xanatos