“收集被修改......”问题

时间:2010-05-25 03:13:01

标签: c# collections exception

我有一个函数可以检查对象列表,看它们是否被点击并相应地触发OnClick事件。我相信功能正常,但是我遇到了问题:

当我挂钩其中一个OnClick事件并删除并将该元素插入列表中的其他位置时(此程序的典型功能),我收到“Collection was modified ...”错误。

我相信我明白发生了什么:

  • 该函数循环访问每个对象,在必要时触发OnClick事件
  • 触发一个事件,并且对象根据钩子函数
  • 更改列表中的位置
  • 在迭代过程中修改集合时抛出异常

我的问题是,如何让我允许函数遍历所有对象,在适当的时间触发必要的事件,并仍然让用户选择操作对象在列表中的位置?

5 个答案:

答案 0 :(得分:7)

这类问题有两种通用解决方案:

  • 复制清单。迭代副本。
  • 列出需要进行的更改。完成迭代后应用更改。

如果您想要从进行循环的代码中解除更改的代码,那么“使用索引”选项听起来不合适。

答案 1 :(得分:2)

  • 使用集合的副本而不是初始集合进行迭代。

  • 如果您有一个支持索引的集合(如List),您可以使用'for'循环而不是使用'foreach'进行迭代。

答案 2 :(得分:2)

如果您使用foreach循环来操作集合,请尝试使用

替换它
for (int a = items_count - 1; a >= 0; --a)

答案 3 :(得分:2)

您看到的行为是by design

  

C#的foreach声明   语言(在Visual Basic中为每个语言)   掩盖了复杂性   统计员。因此,使用foreach   建议而不是直接   操纵枚举器。

     

可以使用枚举器来阅读   集合中的数据,但他们   不能用来修改   基础集合。

同步执行的事件与在foreach循环中修改集合具有相同的效果。

我的偏好是使用向后的for循环,这可以避免根据是否插入内容来更新循环索引的条件逻辑:

for (var i = collection.Count - 1; i >= 0; i--) {
  if (condition)
    collection.Insert(i, item);
}

相应的递增循环将如下所示:

for (var i = 0; i < collection.Count; i++) {
  if (condition) {
    collection.Insert(i, item);
    i++;
  }
}

答案 4 :(得分:1)

集合在迭代时无法修改。您需要先标记要从集合中删除的项目,然后将其删除。您可以根据您的要求在删除项目之前或之后触发事件。此代码段显示了我与

相关的内容

列出itemsTobeRemoved = new List(); for(var i = 0; i&lt; collection.Count; i ++){   if(condition){ itemsTobeRemoved.Add(ⅰ); }

foreach(itemsTobeRemoved中的var i = 0){   if(condition){ collection.RemoveAt(ⅰ); }