Whether the selection is being made. Where is the result in two iterations over IEnumerable?

Say I have

IEnumerable<int> list = new int[] { 1, 2, 3 };
List<int> filtered = list.Select(item => item * 10).Where(item => item < 20).ToList();

The question is whether there are two iterations or only one.

In other words, this is equivalent in performance:

IEnumerable<int> list = new int[] { 1, 2, 3 };
List<int> filtered = new List<int>();
foreach(int item in list) {
    int newItem = item * 10;
    if(newItem < 20)
        filtered.Add(newItem);
}
+5
source share
2 answers

There is one collection iteration that is performed when the method is called .ToArray, so both must be equivalent. .Selectis a projection, and .Whereis a filter, expressed as expression trees in the original dataset.

It can be easily proved:

public class Foo: IEnumerable<int>
{
    public IEnumerator<int> GetEnumerator()
    {
        yield return 1;
        Console.WriteLine("we are at element 1");
        yield return 2;
        Console.WriteLine("we are at element 2");
        yield return 3;
        Console.WriteLine("we are at element 3");
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        throw new NotImplementedException();
    }
}

class Program
{
    static void Main()
    {
        var filtered = new Foo()
            .Select(item => item * 10)
            .Where(item => item < 20)
            .ToList();
    }
}

at startup it prints the following:

we are at element 1
we are at element 2
we are at element 3
+7
source

Linq WHERE SELECT . , foreach ToList ToArray() ..

Linq to SQL , . ToList ToArray(), . db .

+2

All Articles