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');
4 comments:
Hi William
Do you have the book (C# 3.0 in a Nutshell)? The book includes accompanying text that explains how each of the examples work.
I'm just wondering whether you're
(a) confused with the book's explanation - or,
(b) wondering what book says!
Joseph Albahari
(Author)
I don't have the book -- yet. I look forward to reading it, when it my order comes in the mail. I thank you for leaving a comment.
Thanks a lot! I had exactly the same problem!
This happens because of deferred execution. LINQ delays the real execution of queries until they are needed.
By using one exemple of the book itself (chapter 8: LINQ Queries: Deferred Execution):
int[] numbers = { 1, 2 };
int factor = 10;
IEnumerable<int> query = numbers.Select (n => n * factor);
factor = 20;
(...and then you show the results in any way)
Will result:
20
40
The lambda expression have its execution delayed until it is needed (when you show the data), so the value it will use for factor is 20, so both numbers are multiplied by 20, not 10.
Airton da Fonseca Granero
Post a Comment