我有一个函数可以检查对象列表,看它们是否被点击并相应地触发OnClick事件。我相信功能正常,但是我遇到了问题:
当我挂钩其中一个OnClick事件并删除并将该元素插入列表中的其他位置时(此程序的典型功能),我收到“Collection was modified ...”错误。
我相信我明白发生了什么:
我的问题是,如何让我允许函数遍历所有对象,在适当的时间触发必要的事件,并仍然让用户选择操作对象在列表中的位置?
答案 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(ⅰ); }