“集合已修改...”问题
我有一个函数可以检查对象列表以查看它们是否已被单击并相应地触发 OnClick 事件。我相信该函数工作正常,但是我遇到了一个问题:
当我连接到 OnClick 事件之一并将该元素删除并插入到列表中的不同位置(该程序的典型功能)时,我得到“集合已修改...”错误。
我相信我明白发生了什么:
- 该函数在必要时循环遍历每个对象,触发 OnClick 事件
- 触发事件,并且对象根据挂钩函数更改列表中的位置
- 在迭代集合时会抛出异常以修改集合
我的问题是,如何允许函数迭代所有对象,在适当的时间触发必要的事件,并且仍然为用户提供操纵对象在列表中的位置的选项?
I've got a function that checks a list of objects to see if they've been clicked and fires the OnClick events accordingly. I believe the function is working correctly, however I'm having an issue:
When I hook onto one of the OnClick events and remove and insert the element into a different position in the list (typical functionality for this program), I get the "Collection was modified..." error.
I believe I understand what is going on:
- The function cycles through each object firing OnClick events where necessary
- An event is fired and the object changes places in the list per the hooked function
- An exception is thrown for modifying the collection while iterating through it
My question is, how to do I allow the function to iterate through all the objects, fire the necessary events at the proper time and still give the user the option of manipulating the object's position in the list?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
此类问题有两种通用解决方案:
如果您想将进行更改的代码与执行循环的代码分离,“使用索引”选项听起来并不合适。
There are two general solutions to this kind of problem:
The "use indices" option doesn't sound like it's suitable if you want to decouple the code that makes the changes from the code that does the looping.
使用集合的副本而不是初始集合进行迭代。
如果您有一个支持索引的集合(如 List),您可以使用“for”循环,而不是使用“foreach”进行迭代。
Use copy of the collection instead of initial collection for iteration.
If you have a collection that supports indices (like List) you can use 'for' loop instead of iteration with 'foreach'.
如果您使用 foreach 循环来操作集合,请尝试将其替换为
If you are using a foreach loop to manipulate the collection, try replacing it with a
您看到的行为是设计使然:
触发同步执行的事件与在
foreach
循环中修改集合具有相同的效果。我的偏好是使用向后循环的 for 循环,这可以避免根据是否插入某些内容来更新循环索引的条件逻辑:
相应的递增循环将如下所示:
The behaviour you are seeing is by design:
Firing an event, which is synchronously executed has the same effect as modifying the collection from within the
foreach
loop.My preference is to use a
for
loop going backwards, this avoids conditional logic of updating the loop index depending on whether or not you insert something:The corresponding incrementing loop will look something like this:
集合在迭代时不能被修改。您需要先标记要从集合中删除的项目,然后再将其删除。您可以根据您的要求在删除项目之前或之后触发事件。 相关的内容
此代码片段显示了我与List itemsTobeRemoved=new List();
for (var i = 0; i < collection.Count; i++) {
如果(条件){
itemsTobeRemoved.Add(i);
}
foreach (var i = 0 in itemsTobeRemoved) {
如果(条件){
集合.RemoveAt(i);
}
Collections cannot be modified when they are being iterated. You need to mark the items that are to be removed from the collection first and then remove them. You can fire the events before or after the items are removed depending upon your requirement. This code snippet shows what i am pertaining to
List itemsTobeRemoved=new List();
for (var i = 0; i < collection.Count; i++) {
if (condition) {
itemsTobeRemoved.Add(i);
}
foreach (var i = 0 in itemsTobeRemoved) {
if (condition) {
collection.RemoveAt(i);
}