使用Linq进行复制/过滤会在foreach循环中产生动态结果吗?

Luk*_*ves 2 c# linq foreach

所以我创建了一个我想删除的项目字典的投影.

var toRemoveList =
    this.outputDic.Keys.Where(key =>
        this.removeDic.ContainsKey(key));
Run Code Online (Sandbox Code Playgroud)

然后我遍历从实际字典中删除的结果

        foreach(var key in toRemoveList)
            this.outputDic.Remove(key);
Run Code Online (Sandbox Code Playgroud)

但是在该foreach期间抛出一个异常,表示该循环期间修改了列表.但是,怎么这样呢?linq查询是否有点动态,每次字典更改时都会重新评估?查询结尾处的一个简单的.ToArray()调用解决了问题,但是imo,它甚至不应该首先出现.

Eri*_*ert 14

所以我创建了一个我想删除的项目字典的投影.

var toRemoveList =
  this.outputDic.Keys.Where(key =>
    this.removeDic.ContainsKey(key));
Run Code Online (Sandbox Code Playgroud)

正如我经常说的,如果我可以向人们传授关于LINQ的一件事,那就是: 查询表达式的结果是查询,而不是执行查询的结果.你现在有一个对象,意思是"字典的键,使得键是......某种东西".它不是该查询的结果,而是查询.查询本身就是一个对象; 在你要求之前,它不会给你一个结果集.

然后你这样做:

    foreach(var key in toRemoveList)
        this.outputDic.Remove(key);
Run Code Online (Sandbox Code Playgroud)

那么你正在做什么?您正在迭代查询.迭代查询执行查询,因此查询迭代原始字典.但是当你迭代它时,从字典中删除一个项目,这是非法的.

imo,它甚至不应该首先发生.

你对世界应该是怎样的观点是一个普遍的看法,但按照自己的方式去做会导致效率低下.让我们假设创建查询立即执行查询而不是创建查询对象.这是做什么的?

var query = expensiveRemoteDatabase
    .Where(somefilter)
    .Where(someotherfilter)
    .OrderBy(something);
Run Code Online (Sandbox Code Playgroud)

Where生成查询的第一个调用,然后在您的世界中执行,从远程数据库中下拉与该查询匹配的所有记录.然后第二次打电话Where说"哦,对不起,我本来也想在这里应用这个过滤器,我们可以再次进行整个查询,这次使用第二个过滤器吗?" 因此然后整个记录集的计算,然后我们说:"哦,不,等一下,我忘了告诉你,当你建立了一个最后的查询对象,我们将需要对它进行排序,那么数据库,你可以运行这个问题第三次给我?"

现在也许您看到为什么查询生成一个查询,然后在需要之前不会执行?