【问题标题】:using Linq to generate a collection of things to be removed from another collection使用 Linq 生成要从另一个集合中删除的东西的集合
【发布时间】:2010-12-05 09:19:57
【问题描述】:

我熟悉在使用 foreach 循环(即“System.InvalidOperationException: Collection was modified”)循环时修改集合的问题。但是,对我来说,当我使用 Linq 创建要从字典中删除的键列表,然后循环遍历我的新列表时,我得到了同样的异常。

之前的代码,抛出异常:

IEnumerable<Guid> keysToDelete = _outConnections.Where(
    pair => pair.Value < timeoutPoint
).Select(pair => pair.Key);

foreach (Guid key in keysToDelete)
{
    ...some stuff not dealing with keysToDelete...
    _outConnections.Remove(key);
}

之后的代码,有效:

List<Guid> keysToDelete = _outConnections.Where(
    pair => pair.Value < timeoutPoint
).Select(pair => pair.Key).ToList();

for (int i=keysToDelete.Count-1; i>=0; i--)
{
    Guid key = keysToDelete[i];
    ...some stuff not dealing with keysToDelete...
    _outConnections.Remove(key);
}

这是为什么?我有一种感觉,也许我的 Linq 查询并没有真正返回一个新集合,而是原始集合的某个子集,因此当我从 _outConnections 中删除一个元素时,它指责我修改了集合 keysToDelete

更新:以下修复也有效,感谢 Adam Robinson:

List<Guid> keysToDelete = _outConnections.Where(
    pair => pair.Value < timeoutPoint
).Select(pair => pair.Key).ToList();

foreach (Guid key in keysToDelete)
{
    ...some stuff not dealing with keysToDelete...
    _outConnections.Remove(key);
}

【问题讨论】:

  • 如果我可以告诉人们关于 LINQ 查询的一件事,那就是查询表达式的结果是查询本身,而不是查询的结果我>。这种常见的误解是 StackOverflow 上有关 LINQ 的相当一部分问题的基础。
  • 当我发现 Linq 时,我想“哦,嘿,这让我可以在 Ruby 中做类似的事情!”,我仍然在内部考虑像 SelectWhere 这样的方法,就 Ruby 的 @ 而言987654329@ 和 select,它们进行处理并返回新的结果集合。我必须开始在心理上将 Ruby 方法与看起来相似的 Linq 方法区分开来。

标签: c# linq collections loops


【解决方案1】:

你是对的。 LINQ 使用所谓的“延迟执行”。声明您的 LINQ 查询实际上并没有做任何事情,除了构造一个查询表达式。直到您实际枚举列表时才会评估查询,并且它使用原始列表作为源。

但是,调用ToList() 应该会创建一个与原始列表无关的全新列表。检查异常的调用堆栈,确保它实际上是由keysToDelete 抛出的。

【讨论】:

  • 哎呀,忘了我的修复部分涉及添加ToList。最初,我只是使用IEnumerable;更新了问题代码以反映这一点。
  • 哦,根据您的第二段,我可以将我的修复更改为以下之一:1) 删除 ToList 的东西,然后在 IEnumerable 或 2 上使用我的 for 循环) 保留 ToList 内容并切换回使用 foreach 循环,因为新 List 是一个单独的集合。谢谢!
  • 您不能使用for 选项,因为IEnumerable 不支持基于索引的访问。我建议在ToList() 的结果上切换到foreach
  • 同意。我不喜欢那些简单的for 循环,因为它们看起来不像foreach 那样安全。我在问题中添加了我的新解决方案(ToListforeach)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-11
  • 1970-01-01
相关资源
最近更新 更多