“集合已修改...”问题

发布于 2024-09-03 00:03:16 字数 343 浏览 2 评论 0原文

我有一个函数可以检查对象列表以查看它们是否已被单击并相应地触发 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

放飞的风筝 2024-09-10 00:03:16

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

  • 复制该列表。迭代副本。
  • 列出需要发生的改变。完成迭代后应用更改。

如果您想将进行更改的代码与执行循环的代码分离,“使用索引”选项听起来并不合适。

There are two general solutions to this kind of problem:

  • Make a copy of the list. Iterate over the copy.
  • Make a list of the changes that need to happen. Apply the changes after you've finished iterating.

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.

纵山崖 2024-09-10 00:03:16
  • 使用集合的副本而不是初始集合进行迭代。

  • 如果您有一个支持索引的集合(如 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'.

终止放荡 2024-09-10 00:03:16

如果您使用 foreach 循环来操作集合,请尝试将其替换为

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

If you are using a foreach loop to manipulate the collection, try replacing it with a

for (int a = items_count - 1; a >= 0; --a)
朦胧时间 2024-09-10 00:03:16

您看到的行为是设计使然

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

The behaviour you are seeing is by design:

The foreach statement of the C#
language (for each in Visual Basic)
hides the complexity of the
enumerators. Therefore, using foreach
is recommended instead of directly
manipulating the enumerator.

Enumerators can be used to read the
data in the collection, but they
cannot be used to modify the
underlying collection.

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:

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

The corresponding incrementing loop will look something like this:

for (var i = 0; i < collection.Count; i++) {
  if (condition) {
    collection.Insert(i, item);
    i++;
  }
}
深海蓝天 2024-09-10 00:03:16

集合在迭代时不能被修改。您需要先标记要从集合中删除的项目,然后再将其删除。您可以根据您的要求在删除项目之前或之后触发事件。 相关的内容

此代码片段显示了我与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);
}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文