Say I have the the following code:
var myList = new List<int> {1, 2, 3, 4, 5};
var newList = myList.Where(x => x % 2 == 0).Select(x => x * 2);
Does myList
get enumerated over twice (i.e. once for the Where
and once for the Select
), or does it only enumerate once? More generally, when chaining n LINQ method calls, does the collection being selected from only get enumerated once, or n times?
CodePudding user response:
It depends but in your example no.
LINQ has a concept of deferred operations. These only evaluate when the enumeration happens. These are like .Where()
and .Select()
Immediate operations are like .ToList()
that cause a full enumeration.
You can read up on them here. https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/linq/classification-of-standard-query-operators-by-manner-of-execution
CodePudding user response:
No, not normally, that is the point, the result of a call to .Where()
is simply a deferred expression. It is not until you call the enumerator that it actually enumerates, which your code is not doing at all.
After your code:
var myList = new List<int> {1, 2, 3, 4, 5};
var newList = myList.Where(x => x % 2 == 0).Select(x => x * 2);
newList
is an instance of IEnumerable<int>
, it is simply a chain of function call expressions that have not yet been evaluated, or executed.
Later in your code if you store the results into an actual list, the original list will only be iterated once, each function being executed for each item in the list in the order that they were chained in:
var listResult = newList.ToList();
This will first iterate the list as follows
- move to the first item:
1
- evaluate
Where(x => x % 2 == 0)
:false
- this yields a break and ends the evaluation for this item
- move to next item:
2
- evaluate
Where(x => x % 2 == 0)
:true
- project using
Select(x => x * 2)
:4
- yield the value to the output list.
- move to the next item:
3
...