看看这个csharp代码,看看你是否可以告诉我在找到并删除列表中的项目后需要退出循环的原因。想法是通过一个节点的邻居列表,看看那里是否存在Node n,然后删除那个邻居:
internal void RemoveDirected(Node n)
{
foreach (EdgeToNeighbor etn in this.Neighbors)
{
if (etn.Neighbor.Key == n.Key)
{
RemoveDirected(etn);
break;
}
}
}
internal void RemoveDirected(EdgeToNeighbor e)
{
Neighbors.Remove(e);
}
。 。
// Removes EdgeToNeighbor instance from AdjacencyList
protected internal virtual void Remove(EdgeToNeighbor e)
{
base.InnerList.Remove(e);
}
注意我在第一个方法中的RemoveDirected调用后如何“中断”。 我发现如果我在RemoveDirected之后没有退出 它会在foreach循环中永远持续下去。我想它一定有 与foreach的工作方式有关。如果您修改列表 foreach正在努力,它会变得混乱并永远循环。
你见过这种类型的东西,还有什么其他选择可以使用而不是使用break? 当然,我可以将我找到的节点放在局部变量中,然后从循环中断开,然后 在循环之外删除它。但我在想,可能有更好的方法来做到这一点 在csharp。
答案 0 :(得分:8)
使用迭代器迭代.NET集合时,不得修改该集合。如果你这样做,那你就是在寻找麻烦。
您应该推迟删除而不是在foreach
循环中删除权限。例如,您可以在列表中收集需要删除的所有内容,然后在foreach
之外删除它。
var toDelete = this.Neighbors.Where(etn => etn.Neighbor.Key == n.Key).ToList();
foreach (var e in toDelete) {
Neighbors.Remove(e);
}
答案 1 :(得分:1)
如果要删除项目,绝对不想使用迭代器。一种选择是将其更改为向下计数循环:
for (int nI = this.Neighbors.Count; nI >= 0; nI--)
{
var etn = this.Neighbors[nI];
if (etn.Neighbor.Key == n.Key)
{
RemoveDirected(n);
}
}
您还可以收集循环内集合中要删除的键或项目,然后在完成迭代后执行删除。
但是,如果您只删除单个项目并且集合中的项目以某种方式键入,那么您实际上不需要任何循环。只需测试集合中密钥或项目的存在,如果存在,只需将其删除即可。
答案 2 :(得分:0)
您可以获取节点数量,然后在for循环中从最高到最低进行检查和删除,这样您就可以避免查找不再存在的项目。