C# - 集合已修改;枚举操作可能无法执行

Posted

技术标签:

【中文标题】C# - 集合已修改;枚举操作可能无法执行【英文标题】:C# - Collection was modified; enumeration operation may not execute [duplicate] 【发布时间】:2015-06-17 16:26:33 【问题描述】:

在我编写的冗长代码中有一个按钮单击事件。我有一个对象列表。每次单击按钮时,都应修改列表(例如,应删除某些项目),然后使用 foreach 循环进行迭代。

List<Person> lp=new List<Person>();
lp.RemoveAt(2);

foreach(Person j in lp)

    // do something

当我尝试执行上述代码时,它会导致异常。

InvalidOperationException : 集合被修改;枚举操作可能无法执行。

我在互联网上找到了一些解决方案并尝试了它们。其中之一是,

foreach(Person j in lp.ToList())

    // do something

但没有什么可以阻止异常。

有人可以帮忙吗?

【问题讨论】:

List 是否有可能被其他线程访问? 向我们展示循环内的代码 【参考方案1】:

显然,您的 do something 代码正在尝试修改集合。 在迭代集合时修改集合通常是个坏主意。

你可以做什么:

    将集合复制到另一个。

    foreach(Person j in lp.ToArray())
    

    foreach(Person j in new List<Person>(lp))
    

    使用修改项目的临时集合。

    List<Person> itemsToDoSomething = new List<Person>();
    foreach(Person j in lp)
        itemsToDoSomething.Add(j);
    

    然后应用所需的操作。例如,从集合中删除项目:

    lp.RemoveAll(item => itemsToDoSomething.Contains(item));
    

【讨论】:

谢谢!这帮助我解决了它! 不是循环键是个好主意吗? ***.com/a/26864676/1589885 new List(lp) 仍然会在里面复制和 foreach。它仍然会抛出更多可能性! @joe 错了。集合的副本是一个单独的集合,原始集合的更改不会影响它。请参阅docs:“初始化 List&lt;T&gt; 类的新实例,该实例包含从指定集合复制的元素,并且有足够的容量容纳复制的元素数量。”是的,请举个例子。 @Dmitry 是的,它是一个副本。但是复制过程本身不是线程安全的。问题出在运行 ToArray 时。 ToArray 没有解决问题,只是将其迁移到另一个问题:Destination array was not long enough. Check destIndex and length 但不太可能发生,因为 ToArray() 在内部没有任何处理的情况下速度更快。和构造函数版本是一样的实现,通过调用CopyTo这里的例子:dotnetfiddle.net/IqVbZ8【参考方案2】:

尝试修改克隆列表并将引用复制回来(只是一个想法):

List<Person> newList = new List<Person>(lp);lp = newList;

基本上不允许在迭代列表时修改列表

【讨论】:

谢谢!但还是一样 dosomething 确实做了一些修改你正在迭代的列表的事情。 我的意思是遍历您的 lp,但修改 newList(这似乎是您的要求),然后将您的 newList(已修改)分配回您的原始列表(即 lp)

以上是关于C# - 集合已修改;枚举操作可能无法执行的主要内容,如果未能解决你的问题,请参考以下文章

C# 使用定时器和Dictionary 出现异常说集合已修改,可能无法执行枚举操作,求帮忙啊

集合已修改,可能无法执行枚举操作

集合已修改;可能无法执行枚举操作。

集合被修改枚举操作可能无法执行

集合被修改,枚举操作可能无法执行

集合被修改,枚举操作可能无法执行