Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 林克收集差异?_C#_Linq - Fatal编程技术网

C# 林克收集差异?

C# 林克收集差异?,c#,linq,C#,Linq,我有一个关于两位代码的问题,这两位代码乍一看似乎功能相同,但在构建和运行它们时会产生不同的结果 代码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

我有一个关于两位代码的问题,这两位代码乍一看似乎功能相同,但在构建和运行它们时会产生不同的结果

代码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的控制台输出,因为可能剩下的唯一值是绿色,它同时包含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,查询中剩余的值为绿色和棕色。据我所知,原因是因为我们给s赋值,n的值,在它之前保持e的位置。如果我转储查询的内容,它将包含绿色/棕色,尽管我已经将查询缩减到所有包含“e”的值


如果有人能解释为什么会这样,那就太好了,谢谢

由于延迟执行,您将看到不同的结果。也就是说,当你打电话给Where时,它实际上与你的收藏没有任何关系。它只返回一个IEnumerable实现,一旦您尝试访问枚举,它将执行某些操作

因此,在第二个示例中,您在查询lambda中引用了变量s,在执行第一个查询时,您已将该变量更改为值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值计算枚举。随后对变量的更改将不会影响最终结果。

由于延迟执行,您将看到不同的结果。也就是说,当你打电话给Where时,它实际上与你的收藏没有任何关系。它只返回一个IEnumerable实现,一旦您尝试访问枚举,它将执行某些操作

因此,在第二个示例中,您在查询lambda中引用了变量s,在执行第一个查询时,您已将该变量更改为值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值计算枚举。随后对变量的更改将不会影响最终结果。

在第二个代码段中,您正在围绕变量s创建一个闭包。在使用.Count枚举列表之前,不会计算where子句中的表达式。此时,s已经被重新分配,因此where查询实际上是彩色的。在第二个代码段中,您正在围绕变量s创建一个闭包。在使用.Count枚举列表之前,不会计算where子句中的表达式。当时,,s已被重新分配,因此您的where查询实际上是彩色的。Wherec=>c.Containsn.Wherec=>c.Containsn

原因是LINQ查询基于“延迟执行”——该查询是生成的,但不是真正执行的,除非您专门迭代每个循环的集合,例如调用.ToList或.ToArray扩展方法。

原因是LINQ查询基于“延迟执行”——该查询是生成的,但不是真正执行的,除非您专门迭代集合foreach循环,例如call.ToList或.ToArray扩展方法。

当Count调用发生时,您的where逻辑将实际执行。因此,在Console.WriteLine之前,lambda表达式甚至没有执行过一次,导致字符串变量稍后在lambda中的计算结果为n,因为赋值已经执行了-您可以使用调试器检查这一点。这个概念在查询数据库时被调用,并且非常有用,因为SQL是在整个查询已知的情况下对数据库编译和运行的。

当Count调用发生时,您的where逻辑将实际执行。因此,在Console.WriteLine之前,lambda表达式甚至没有执行过一次,导致字符串变量稍后在lambda中的计算结果为n,因为赋值已经执行了-您可以使用调试器检查这一点。这个概念在查询数据库时被调用,并且非常有用,因为SQL是在整个查询已知的情况下对数据库进行编译和运行的。

是的,您是对的,这是因为s=n; Linq是惰性的。在您的示例中,第一个未直接计算。仅当需要迭代时。而且因为其中lambda捕获了s变量,所以当前值甚至用于第一个lambda。 在第二个IEnumerable之前尝试ToList,强制计算第一个IEnumerable

String[] colors = { "green", "red", "blue", "brown" };
string s = "e";
var query = colors.Where(c => c.Contains(s)).ToList();

s = "n";
query = query.Where(c => c.Contains("n"));

是的,你是对的,这是因为s=n; Linq是惰性的。在您的示例中,第一个未直接计算。Onl 当需要迭代时,返回y。而且因为其中lambda捕获了s变量,所以当前值甚至用于第一个lambda。 在第二个IEnumerable之前尝试ToList,强制计算第一个IEnumerable

String[] colors = { "green", "red", "blue", "brown" };
string s = "e";
var query = colors.Where(c => c.Contains(s)).ToList();

s = "n";
query = query.Where(c => c.Contains("n"));