Few days ago I was watching the Scott Allen’s video
where he shows some interesting tips and tricks and ways to optimize
your LINQ code. The following blog refers to one of his first tips in
the video, so I’ve tried some tests which I’m going to explain here.
This will be a basic scenario using LINQ. The idea is to show how and when does LINQ executes.
Lets take a look at the following code
I’ve created a source list that contain some random number elements.
Then, I’m querying the list using LINQ and put the result in a ‘result’
variable. As you can notice, I’ve surrounded the statement in
parenthesis and have called on it the ToList() method. We all know what
will this method do, it will simply convert the IEnumerable result into
List. Ok, everything is fine and the ‘result’ will be of List type.
we move forward, we decide to add another values in the source list (40
and 41 in our example). The last part of the code is the foreach
statement which just prints all the elements from result list in the web
application. Since I’ve made condition to find the even numbers (using
mod), the result will be: 4 18 20 30
That was expected,
or not? I think yes since its logical and these are the values that were
filtered from the source list and stored in the result list.
Ok, lets move with the same code so that we won’t convert the result from the query to List.
Everything is the same except we don’t have the ToList() method. It means that the result variable won’t be of List type but it will remain IEnumerable. So, what’s the trick here?
The result now is: 4 18 20 30 40
40? From where it came? We have added 40 to the source collection, not
to the result collection and the result collection was created
previously not after the code lines where we add new values to the
source collection, then is this a wrong behavior or what?
It’s definitely NOT a wrong behavior. That’s actually a deferred execution
because the IEnumerable is not enumerated all until you cal it
explicitly to enumerate it, such as in FOREACH loop. The result variable
holds the definition of the LINQ statement and the source list. If you
look in debug mode, you will see this
If you try to see the Result View, here is what it says
the Result View will enumerate the IEnumerable” – as I’ve said
previously, the IEnumerable is not enumerated. So, if you click on the
refresh-like icon – it will expand the Result View and you will see the
result, however, the result is not enumerated on runtime, which means,
if we add another elements in the source collection, these elements will
be taken into consideration on the result collection. The result
collection will be enumerated once it’s called for that. So, after we’ve
added the 40 and 41 values to the source list, here is what values we
have in the result:
see that we now have 13 elements (previously we had 11) including the
last two elements (40 and 41) added in the source list.
once we call the foreach statement the result will be enumerated and
that’s why 40 is included in the result now because the LINQ statement
is executed once the result is enumerated and not in the time when the
query is defined.
I hope this was an useful info for you.
Kind Regards, Hajan