2010-05-25 83 views
2

我有一个函数,它检查对象列表以查看它们是否被点击并相应地触发了OnClick事件。我相信该功能正常工作,但我有一个问题:“Collection was modified ...”问题

当我钩到一个OnClick事件,并删除并插入元素到列表中的不同位置(此程序的典型功能),我收到“收集已修改...”错误。

我相信我明白是怎么回事:发射必要的onclick事件经过的每个对象

  • 函数周期
  • 触发一个事件和对象改变的地方以每挂钩函数
  • 列表
  • 抛出异常的修改集合,而通过它迭代

我的问题是,如何做我允许的功能通过迭代将对象,在适当的时候触发必要的事件,并仍然允许用户选择操纵对象在列表中的位置?

回答

7

有这类的问题,有两种解决办法一般:

  • 榜上无名的副本。迭代副本。
  • 列出需要进行的更改。迭代完成后应用更改。

如果您想要将代码与执行循环的代码分离开来,那么“use indices”选项听起来并不合适。

+0

我认为第二个选项听起来最好。我将在更新过程中记录对列表的任何修改,然后在迭代完成后应用它们。 – 2010-05-25 13:56:00

+0

请注意,当您进行多个编辑 - “交换1和2”和“交换2和3”或“在A之后移动C”和“删除”时,您必须清楚“一个”。我通常会发现,通过迭代副本来制作正确的代码会更容易,尽管它可能非常低效。 – 2010-05-26 11:25:07

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

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

+0

或者,List <> .ForEach() – Alan 2010-05-25 03:21:17

+0

foreach仍然会导致相同的错误。 – 2010-05-25 03:21:49

2

如果您使用的是foreach循环操作集合,尝试用

for (int a = items_count - 1; a >= 0; --a) 
+1

只有当您有索引直接访问收集项目时,这才算正常。 – 2010-05-25 03:58:17

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++; 
    } 
} 
1

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

List itemsTobeRemoved = new List();对于(var i = 0; i < collection.Count; i ++)if(condition){ itemsTobeRemoved.Add(i); }

的foreach(VAR I =在itemsTobeRemoved 0){ 如果(条件){ collection.RemoveAt(ⅰ); }