c# - 避免集合已修改错误

标签 c# collections ienumerable enumeration

问题:

我有以下代码:

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

显然我收到了一个错误。

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

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

想法:也许看看 GetEnumerator 何时被调用?也许用IDisposable做一些聪明的事情?

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

注意我想避免任何不必要的复制,因为我想消除/最小化垃圾收集,所以我不能只是迭代副本/创建新副本或类似的东西。

最佳答案

您提到了 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() 并忘记释放枚举器,这可能会变得很糟糕。

关于c# - 避免集合已修改错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6305228/

相关文章:

C#:如何根据子元素的属性过滤 XML 文件的结果?

c# - 如何使 Microsoft.Web.Helpers.ReCaptcha 与 X-Forwarded-Proto 一起使用

c# - 什么时候在 mvvm 中使用 Dispatcher?

java - 为什么 Hashmap 允许空键?

java - 获取集合元素的最快方法是什么?

c# - 为什么我们不能为以下代码调试带有 yield return 的方法?

c# - 如果长度恰好为一个,或者否则为默认值,我如何获得 IEnumerable 的第一个值?

c# - C# 应用程序的图像监视

c# - 在网络配置文件中添加或编辑

c# - 如何检测 BindingList<T> 中项目属性的更改?