我有一个问题,关于两段代码,这些代码乍一看似乎以相同的方式运行,但在我构建和运行它们时却产生不同的结果。
代码A:
String[] colors = {"green", "red", "blue", "brown"};
var query = colors.Where(c => c.Contains("e"));
query = query.Where(c=> c.Contains("n"));
Console.WriteLine(query.Count());
这会产生控制台输出“1”,因为大概剩下的唯一值是“green”(同时包含 e 和 n)。
如果代码稍作改动,结果就会不同
代码 B:
String[] colors = {"green", "red", "blue", "brown"};
string s = "e";
var query = colors.Where(c => c.Contains(s));
s = "n";
query = query.Where(c=> c.Contains("n"));
Console.WriteLine(query.Count());
这会产生控制台输出“2”,“query”中剩余的值为“green, brown”。据我所知,原因是因为我们将 s 的值赋给了之前包含“e”的“n”。如果我转储“查询”的内容,它将包含“绿色/棕色”,尽管我已经将查询缩减为包含“e”的所有值。
如果有人能解释为什么会发生这种情况,那就太好了,谢谢!
请您参考如下方法:
由于“延迟执行”,您会看到不同的结果。 IE。当你调用Where() ,它实际上不会对您的收藏做任何事情。它只返回一个 IEnumerable<string>一旦您尝试访问枚举,将执行某些操作的实现。
所以在你的第二个例子中,你引用了变量 s在您的查询 lambda 中,在执行第一个查询时,您已将变量更改为值 "n" ,因此两个查询都执行相同的过滤,返回 2 的完整计数。
请注意,如果您更改代码示例,使其看起来像这样:
String[] colors = {"green", "red", "blue", "brown"};
string s = "e";
var query = colors.Where(c => c.Contains(s)).ToArray();
s = "n";
query = query.Where(c=> c.Contains("n"));
Console.WriteLine(query.Count());
…它会产生你期望的结果。以上调用ToArray()使用 s 的当前值强制对枚举进行评估当时。以后对变量的更改不会影响最终结果。
