Looking at this (admittedly old) answer: Does "foreach" cause repeated Linq execution?
It depends on the dataset to an extent; but because of how LINQ and IEnumerables work, A & C are both the same in terms of functionality. Instead of executing the query in a single-hit; the results are retrieved in a streaming manner, meaning one by one. Each time the iterator calls MoveNext
the projection is applied to the next object; because there's a where clause in your example it applies the filter before the projection.
By calling the .ToList()
method in examples B & D, you're forcing the query to execute and the result to cached. In terms of the "which one is better" question, that's where the answer becomes "it depends".
If the dataset are already in-memory objects; A & C both save a bit on memory, and are slightly quicker than B & D because it's not having to do any manipulation in terms of resizing the list.
If you're querying a database, then A & C save on memory; however (you'd have to test this bit, because it seems hit and miss) it's possible that it'd go back the DB each time the MoveNext
is hit - on a small table it wouldn't make much difference, but I have encountered instances in large tables where it's saved several minutes worth of execution time just by creating a local list of the query results.
EDIT for clarity:
Adding in some pseudocode to elaborate on this point. The premise behind how A & C work is as follows:
- Look for an element that meets the criteria.
- Get the first element that meets the selection criteria.
- Do whatever is within the loop.
- Look for another element.
- Get the next element.
- Do whatever is within the loop.
- Repeat steps 4-6 until a result is not found.
Whereas B & D work more along the lines of the following:
- Find all elements that match the selection criteria.
- Create a list from the results to step 1.
- Assign a pointer that points at the first element in the list.
- Do the code within the loop.
- Move the pointer to the next item in the list.
- Do the code within the loop.
- Repeat steps 5 and 6 for all items in the list.
A more real-life scenario that can roughly explain it is when you go shopping - if you have the shopping list in your hand, because you've already spent the time to figure out what you need, (B & D) then you just need to look at the list and grab the next item. If you don't have the shopping list (A & C), then you have the extra step in the store of thinking "what do I need?" before retrieving the item.