【问题标题】:Adding nodes to LinkedList<T> in foreach在 foreach 中将节点添加到 LinkedList<T>
【发布时间】:2010-08-08 19:23:09
【问题描述】:

我可以在 foreach 语句中安全地将节点添加到 LinkedList 容器吗?如果我使用while循环有什么区别吗?还是永远不允许这样做会导致一些问题?

foreach(var node in myList)
{
    if(condition)
        myList.AddLast(new MyNode());
}

它会总是工作吗?

【问题讨论】:

    标签: .net foreach linked-list


    【解决方案1】:

    枚举时不能修改集合。

    来自docs for LinkedList&lt;T&gt;.GetEnumerator

    枚举数保持有效,只要 集合保持不变。如果 对集合进行了更改, 例如添加、修改或删除 元素,枚举数是 不可恢复的无效及其 行为未定义。

    在实践中,我相信它总是会抛出 InvalidOperationException,尽管该行为未正式定义。

    编辑:您在评论中询问while 循环是否有帮助...使用GetEnumerator/MoveNext/Current 的while 循环不会,但这会:

    LinkedListNode<MyNode> current = myList.First;
    while (current != null)
    {
        if (condition) // use current.Value to get the value
        {
            myList.AddLast(new MyNode());
        }
        current = current.Next;
    }
    

    据我所知,这是完全安全且可预测的。您始终可以向节点询问其下一个节点。如果您碰巧正在查看尾节点并添加另一个,当您要求“下一个”时,您将获得新的尾节点。

    如果这没有帮助,请向我们提供有关您想要实现的目标的更多详细信息。

    【讨论】:

    • 如果新节点符合条件,则完全安全的是一个延伸、无限循环和OOM。
    【解决方案2】:

    不,枚举器对象记住拥有集合的内部版本。集合修改后 - 版本改变,所以 foreach 会失败。

    【讨论】:

    • +1 使用反射器查看枚举器是如何实施检查的:)
    【解决方案3】:

    使用foreach 语句迭代集合时,您不能修改它。因此,添加项目将导致编译器错误。

    【讨论】:

    • 您可以使用while 循环遍历集合。执行此操作时您不会收到编译器错误,但请注意不要编写无限循环 - 如果 new MyNode() 满足 condition 可能会发生这种情况。
    • 不会导致编译器错误。给出的代码将毫无问题地编译。它会在执行时抛出异常。
    • @Jon Skeet:糟糕——我只记得 Visual Studio 抱怨过这段代码,并认为这是编译器错误......谢谢!
    【解决方案4】:

    也许您可以将它们添加到新列表中。然后在最后,在 foreach 之外使用 .addrange() 将新的附加到原始列表中。

    【讨论】:

      猜你喜欢
      • 2010-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多