第一声明:
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');
String.Join("", query)
的输出:"Nt wht y mght xpct"
第二声明:
query = "Not what you might expect";
foreach (char vowel in "aeiou")
query = query.Where (c => c != vowel);
String.Join("", query)
的输出:"Not what yo might expect"
这些陈述的输出是不同的。 任何人都可以解释原因吗?
答案 0 :(得分:57)
如果你使用的C#版本低于5.0(这是固定的),这就是原因:
查询中的lambda捕获循环变量vowel
因为Linq喜欢使用延迟执行,所以在查询执行(通过迭代)之后才会读取此引用的值,这是在foreach
循环完成之后。此时,vowel
的最新值为u
,这就是您获得意外输出的原因。
您可以通过将值复制到另一个临时变量(或升级到C#5.0)来解决此问题。
试试这个:
query = "Probably what you might expect";
foreach (char vowel in "aeiou") {
char currentVowel = vowel;
query = query.Where (c => c != currentVowel );
}
答案 1 :(得分:13)
这是因为你在vowel
变量上创建了一个闭包,它随时间变化。将其值存储在单独的变量中,它将起作用:
query = "Not what you might expect";
foreach (char vowel in "aeiou")
{
var current = vowel;
query = query.Where (c => c != current);
}
答案 2 :(得分:11)
了解关闭。如果您使用.NET 4.0
及以下,则会得到不同的结果。在.NET 4.5
中,此行为已更改(已修复)。另请参阅编译器如何展开foreach
。