LINQ Query - Explanation needed of why these examples are different

前端 未结 2 1681
醉酒成梦
醉酒成梦 2021-02-15 16:50

I\'m reading the book \"LINQ Pocket Reference\" and there is a particular example (slightly modified below) that I\'m having difficulty getting my head around... The explanation

2条回答
  •  臣服心动
    2021-02-15 17:54

    What happens with the first example is that the value of vowel is captured into a local (to the scope of the for-loop) variable.

    The where-clause for the query will then use that captured variable. Where-clauses like this uses an anonymous method/lambda method, which can capture local variables. What happens then is that it captures the current value of the variable.

    In the second class, however, it doesn't capture the current value, only which variable to use, and thus since this variable changes, each time you execute the loop, you build a new Where-clause on top of the last one, but you kinda modify all the preceding ones as well since you change the variable.

    So in the first example, you get this type of query:

    IEnumerable query2 = "Not what you might expect";
    Char t1 = 'a'; query2 = query2.Where(c => c != t1);
    Char t2 = 'e'; query2 = query2.Where(c => c != t2);
    Char t3 = 'i'; query2 = query2.Where(c => c != t3);
    Char t4 = 'o'; query2 = query2.Where(c => c != t4);
    Char t5 = 'u'; query2 = query2.Where(c => c != t5);
    

    In the second example, you get this:

    IEnumerable query2 = "Not what you might expect";
    Char vowel = 'a'; query2 = query2.Where(c => c != vowel);
    vowel = 'e'; query2 = query2.Where(c => c != vowel);
    vowel = 'i'; query2 = query2.Where(c => c != vowel);
    vowel = 'o'; query2 = query2.Where(c => c != vowel);
    vowel = 'u'; query2 = query2.Where(c => c != vowel);
    

    By the time you execute this second example, the value of vowel will be 'u', so only the u will be stripped out. You have, however, 5 loops over the same string to strip out the 'u', but only the first one will of course do it.

    This capturing of variables is one of the things we all trip over when using anonymous methods/lambdas, and you can read more about it here: C# In Depth: The Beauty of Closures.

    If you browse down that page to the text under Comparing capture strategies: complexity vs power, you'll find some examples of this behaviour.

提交回复
热议问题