Started using LINQPad and going through the "C# 3.0 in a Nutshell" tutorial that came with the program.
Then I ran the following script from "Chapter 8 - LINQ Queries/Deferred Execution/Outer Variables in a Loop" :
IEnumerable<char> query = "Not what you might expect";
query = query.Where (c => c != 'a');
query = query.Where (c => c != 'e');
query = query.Where (c => c != 'i');
query = query.Where (c => c != 'o');
query = query.Where (c => c != 'u');
new string (query.ToArray()).Dump ("All vowels are stripped, as you'd expect.");
query = "Not what you might expect";
foreach (char vowel in "aeiou")
{
query = query.Where (c => c != vowel);
}
new string (query.ToArray()).Dump ("Notice that only the 'u' is stripped!");
with the following results:
▪ All vowels are stripped, as you'd expect.
Nt wht y mght xpct
▪ Notice that only the 'u' is stripped!
Not what yo might expect
Very confusing hmmm..., here is the solution (add a temp variable):
foreach (char vowel in "aeiou")
{
char temp = vowel;
query = query.Where (c => c != temp);
}
Reason:
"The temporary variable in the loop is required to avoid the outer variable trap, where the same variable is captured for each iteration of the foreach loop." -- C# 3.0 IN A NUTSHELL http://www.albahari.com/nutshell/predicatebuilder.html
I would like a more detail explanation of this.
I'm guessing that the variable vowel goes through some sort of reset each time the foreach loop is ran, so in the end you will be actually checking
query = query.Where (c => c != 'u');
query = query.Where (c => c != 'u');
query = query.Where (c => c != 'u');
query = query.Where (c => c != 'u');
query = query.Where (c => c != 'u');
instead of
query = query.Where (c => c != 'a');
query = query.Where (c => c != 'e');
query = query.Where (c => c != 'i');
query = query.Where (c => c != 'o');
query = query.Where (c => c != 'u');