为什么这些linq输出不同?

时间:2013-02-27 13:39:04

标签: c# linq

第一声明:

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"

这些陈述的输出是不同的。 任何人都可以解释原因吗?

3 个答案:

答案 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