(Edit after closing: the duplicate is not a duplicate of my question, but I found my answers within an explanation of lazy evaluation.)
Original question:
Disclaimers:
- this is my 1st question here,
- I'm neither a Linq nor a database professional,
- I cannot use Visual Studio at the moment to compile/test any code.
I have puzzles but not the big picture of how Linq works, yet:
- I know from the documentation of where that it returns an IEnumerable which won't be null but can be empty,
- I found the Operators by Manner of Execution table by google, so I know what is a deferred execution,
- I searched the SO site and found order execution of chain, plus debug example of Linq flow.
This last 2 point makes me conclude Linq(-to-Objects) as oppose to databases, does not have predefined execution order for clauses and other query optimizations. (In case there is any difference I'm interested in query syntax as well but I'll only provide examples with functional syntax.)
So, when I write my Linq code like this:
var firstManagerToFire = firedEmployees.Where(x => x.HaveNotBeenFired)
.OfType<Manager>()
.SkipWhile(x => x.Reputation > 0)
.FirstOrDefault();
Was OfType
and SkipWhile
executed?
And what if I reverse the logic:
var FirstManagerToFire = firedEmployees.OfType<Manager>()
.SkipWhile(x => x.Reputation > 0)
.Where(x => x.HaveNotBeenFired)
.FirstOrDefault();
Was OfType
and SkipWhile
executed?
If yes, then does Where
(the 2nd) executes in the following example:
var managersToFire = firedEmployees.OfType<Manager>()
.Except(firedEmployees.Where(x => !x.HaveNotBeenFired))
.Where(x => x.HaveNotBeenFired)
.ToArray();
Does it matter (in terms of executing Where
) if I force an immediate execution within Except
(in this or in any other case)?
.Except(firedEmployees.Where(x => !x.HaveNotBeenFired).ToList())
I can imagine this brings enough detail for the JIT(?) to not execute Where
.
Edit:
Thanks for all the useful comments! If they are all executed, how? Is it like:
public static IEnumerable<TResult> OfType<TSource, TResult>(this TSource source)
{
foreach (var item in source)
#region unreached area when empty
if (item is TResult)
yield return item as TResult;
#endregion
}
public static IEnumerable<TSource> Where<TSource>(this TSource source, Func<TSource, bool> MatchesFilter)
{
foreach (var item in source)
#region unreached area when empty
if (MatchesFilter(item))
yield return item;
#endregion
}