Avoid Collection已被修改错误

本文关键字:修改 错误 Collection Avoid | 更新日期: 2023-09-27 17:58:46

问题:

我有以下代码:

foreach(var ItemA in GenericListInstanceB)
{
    ItemA.MethodThatCouldRemoveAnyItemInGenericListInstanceB();
}

很明显我犯了一个错误。

我想做的是将GenericListInstanceB更改为我创建的类,以跟踪它应该删除的项。然后,当循环结束时,它会将它们全部删除。与添加项目相同。

这很好,我可以创建一个类,它有一个内部列表,以及一个要添加和删除的项目列表。然后是另一个名为AddRemovePendingItems的方法,它实际上"更新"了列表(相应地删除和添加项目)。棘手的部分是让该方法自动调用。

想法:也许看看什么时候调用GetEnumerator?也许用IDisposable做点聪明的事?

问题:我如何知道for循环何时退出,并且我们已经完成了对我的集合类的迭代,以便我可以调用我的AddRemovePendingItems方法?,尤其是如果循环中断早的话?

注意我想避免任何不必要的复制,因为我想消除/尽量减少垃圾收集,这样我就不能只迭代一个副本/制作一个新副本或类似的东西。

Avoid Collection已被修改错误

您提到了IDisposable,它提供了一种实现此功能的方法:

public class GenericList<T> : IList<T>
{
    private class CleanupEnumerator<T> : IEnumerator<T>
    {
        private readonly GenericList<T> source;
        public CleanupEnumerator<T>(GenericList<T> source)
        {
            this.source = source;
        }
        public void Dispose()
        {
            source.RemovePendingDeletes();
        }
        /* Other IEnumerator methods here */
    }
    public IEnumerator<T> GetEnumerator()
    {
        return new CleanupEnumerator(this);
    }
    /* Other IList methods here */
}

这将保证在任何时候使用foreach枚举集合时,都会在释放枚举器时调用RemovePendingDeletes()函数。但是,请注意,如果您直接调用GetEnumerator()并忘记处理枚举器,这可能会变得很糟糕。

这个怎么样。我假设MethodThatCouldRemoveAnyItemInGenericListInstanceB函数从列表中的任何位置删除一个项目或不删除任何项目,则不会添加任何项目。

bool finished = false;
int i = 0;
while (!finished)
{
    var itemA = genericListInstanceB[i];
    itemA.MethodThatCouldRemoveAnyItemInGenericListInstanceB();
    if (genericListInstanceB[i] == itemA)
        i++;
        // All other outcomes result in us leaving i alone
    finished = (i > (genericListInstanceB.Count - 1));
}

危险、过时、"有臭味",但它可以随心所欲,而不必有一个专门的清单或一些魔法来诱捕清单的处理。