Lazy expression evaluation

What will we find in result after this code finished?

IEnumerable<string> src = new List<string> { "ab", "ac", "bc", "abc" };
List<string> filter = new List<string> { "a", "b", "c" };

foreach (var f in filter)
{
   src = src.Where(i => i.Contains(f));
}

result = src.ToList();

You say: only one element: “abc”?
Wrong!
It contains three elements: “ac”, “bc”, “abc”
Why?
Where() is lazy!
Excerpt from help:

“This method is implemented by using deferred execution. The immediate return value is an object that stores all the information that is required to perform the action. The query represented by this method is not executed until the object is enumerated either by calling its GetEnumerator method directly or by using foreach in Visual C# or For Each in Visual Basic.”

We build a lazy evaluated expression chain there will be references to f variable. After we get out from cycle the reference to f remains in use, but it’s value will be the last one it got in the cycle.
So when we evaluate with ToList() call the src.Where(…).Where(…).Where(…) expression each lambda will look for “c”!

This behaviour changes in .NET 4.5; f will encapsulate the value and not the reference.

This entry was tagged , .

Leave a Reply