为什么这些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 ); }
这是因为你在vowel
variables上创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
。