12

我可以看到为什么不允许这样做:

foreach (Thing t in myCollection) {
   if (shouldDelete(t) {
      myCollection.Delete(t);
   }
}

但是这个怎么样?

foreach (Thing t in myCollection.Where(o=>shouldDelete(o)) {
   myCollection.Delete(t);
}

我不明白为什么这会失败。“Where()”方法显然没有返回原始集合,因此当我尝试从中删除某些内容时,我没有枚举原始集合。

4

6 回答 6

26

我不明白为什么这会失败。

我假设您的问题是“为什么会失败?” (你忘了在你的问题中实际提出一个问题。)

“Where()”方法显然没有返回原始集合

正确的。“Where”返回一个IEnumerable<T>代表集合的集合,上面有一个过滤器。

因此,当我尝试从中删除某些内容时,我不会枚举原始集合。

不正确。您正在枚举原始集合。您正在枚举原始集合,并在其顶部放置一个过滤器

当您调用“Where”时,它不会急切地评估过滤器并生成应用了过滤器的原始集合的全新副本。相反,它为您提供了一个枚举原始集合的对象,但会跳过与过滤器不匹配的项目。

当你在商店里说“给我看一切”时,向你展示一切的人会告诉你一切。当你说“现在给我看看每公斤 1 到 5 美元的苹果”时,你并不是在建造一个只有苹果的全新商店。您正在查看与以前完全相同的内容集合,只是上面有一个过滤器。

于 2012-04-16T13:49:45.583 回答
13

尝试使用此代码

myCollection.RemoveAll(x => x.shouldDelete(x));
于 2012-04-16T13:14:46.727 回答
9

你可以做:

myCollection.RemoveAll(shouldDelete);
于 2012-04-16T13:14:59.293 回答
6

第二条语句返回IEnumerable<>对您的列表进行的操作。这个应该没问题:

foreach (Thing t in myCollection.Where(o=>shouldDelete(o).ToList()) {
   myCollection.Delete(t);
}
于 2012-04-16T13:14:36.567 回答
2

这是因为不应该使用 foreach 循环修改集合。它会在执行整个 foreach 循环之前尝试将其删除。因此它会失败。

于 2012-04-16T13:13:18.200 回答
1

其中扩展方法根据传递的谓词过滤集合值并返回 IEnumerable。因此无法在迭代时修改集合。

您可以将 RemoveAll() 用于您的目的。

于 2012-04-16T13:17:41.593 回答