为什么这些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)输出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)输出String.Join("", query)"Not what yo might expect"

这些陈述的输出是不同的。 任何人都可以解释为什么?

如果您使用的是C#版本低于5.0(这是固定的),这是原因:

查询中的lambda捕获循环variablesvowel
由于Linq喜欢使用延迟执行,直到查询被执行(通过遍历它),这个引用的值才会被读取,这是在foreach循环完成之后。 在这一点上, vowel最近值是u ,这就是为什么你会得到意想不到的输出。

您可以通过将该值复制到另一个临时variables(或通过升级到C#5.0)来解决此问题。

尝试这个:

 query = "Probably what you might expect"; foreach (char vowel in "aeiou") { char currentVowel = vowel; query = query.Where (c => c != currentVowel ); } 

这是因为你在vowelvariables上创build了一个闭包,这个variables在时间上发生了变化。 将其值存储在一个单独的variables,它将工作:

 query = "Not what you might expect"; foreach (char vowel in "aeiou") { var current = vowel; query = query.Where (c => c != current); } 

阅读closures。 如果您使用.NET 4.0及以下.NET 4.0 ,您将得到不同的结果。 在.NET 4.5这个行为被改变(固定)。 另请参阅编译器如何扩展foreach