我正在阅读"LINQ Pocket Reference"一书,并且有一个特殊的例子(下面稍作修改),我很难理解......书中的解释有点简短,所以我想知道是否有人可以一步一步地分解它,这样才有意义......
IEnumerable<char> query2 = "Not what you might expect";
foreach (char vowel in "aeiou")
{
var t = vowel;
query2 = query2.Where(c => c != t);
// iterate through query and output (snipped for brevity)
}
Run Code Online (Sandbox Code Playgroud)
输出:
Not wht you might expect
Not wht you might xpct
Not wht you mght xpct
Nt wht yu mght xpct
Nt wht y mght xpct
这对我来说很有意义......然而,事实并非如此.
IEnumerable<char> query2 = "Not what you might expect";
foreach (char vowel in "aeiou")
{
query2 = query2.Where(c => c != vowel);
// iterate through query and output (snipped for brevity)
}
Run Code Online (Sandbox Code Playgroud)
Not wht you might expect
Not what you might xpct
Not what you mght expect
Nt what yu might expect
Not what yo might expect
哪个没...
有人能给我一个更好的解释,确切地说这里发生了什么?
ang*_*son 10
第一个例子的结果是元音的值被捕获到局部(到for循环的范围)变量中.
然后,查询的where子句将使用捕获的变量.像这样的where子句使用匿名方法/ lambda方法,它可以捕获局部变量.然后会发生的是它捕获变量的当前值.
但是,在第二个类中,它不捕获当前值,只捕获要使用的变量,因此,由于此变量发生更改,因此每次执行循环时,都会在最后一个上构建一个新的Where子句,但是你有点修改所有前面的那些,因为你改变了变量.
因此,在第一个示例中,您将获得此类查询:
IEnumerable<char> 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);
Run Code Online (Sandbox Code Playgroud)
在第二个例子中,你得到这个:
IEnumerable<char> 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);
Run Code Online (Sandbox Code Playgroud)
当你执行第二个例子时,值vowel将是'u',所以只有u才会被删除.但是,你在同一个字符串上有5个循环去除'u',但只有第一个当然会这样做.
这个变量的捕获是我们在使用匿名方法/ lambda时所遇到的事情之一,你可以在这里阅读更多相关内容:C#深度:闭包之美.
如果您将该页面浏览到比较捕获策略:复杂性与功能下的文本,您将找到此行为的一些示例.