Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# &引用;集合已修改…”;问题_C#_Collections_Exception - Fatal编程技术网

C# &引用;集合已修改…”;问题

C# &引用;集合已修改…”;问题,c#,collections,exception,C#,Collections,Exception,我有一个函数,它检查对象列表,查看它们是否被单击,并相应地触发OnClick事件。我相信该功能工作正常,但我有一个问题: 当我钩住一个OnClick事件并移除元素并将其插入列表中的不同位置(此程序的典型功能)时,我得到了“Collection was modified…”错误 我相信我了解正在发生的事情: 必要时,该函数循环遍历每个对象触发OnClick事件 触发一个事件,对象根据钩住的函数更改列表中的位置 在遍历集合时修改集合会引发异常 我的问题是,如何允许函数遍历所有对象,在适当的时间触

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

当我钩住一个OnClick事件并移除元素并将其插入列表中的不同位置(此程序的典型功能)时,我得到了“Collection was modified…”错误

我相信我了解正在发生的事情:

  • 必要时,该函数循环遍历每个对象触发OnClick事件
  • 触发一个事件,对象根据钩住的函数更改列表中的位置
  • 在遍历集合时修改集合会引发异常
我的问题是,如何允许函数遍历所有对象,在适当的时间触发必要的事件,并且仍然允许用户选择操作对象在列表中的位置?

  • 在迭代中使用集合的副本而不是初始集合

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


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

      • 把清单复印一份。在副本上迭代
      • 列出需要进行的更改。完成迭代后应用更改

      如果要将进行更改的代码与执行循环的代码解耦,“使用索引”选项听起来不合适。

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

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

      您看到的行为是:

      C语言的foreach语句# 语言(适用于Visual Basic中的每种语言) 隐藏了问题的复杂性 统计员。因此,使用foreach 建议使用,而不是直接使用 操作枚举数

      枚举数可用于读取 集合中的数据,但它们 无法用于修改 基础集合

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

      我的首选是使用
      进行反向循环,这避免了根据是否插入内容更新循环索引的条件逻辑:

      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++;
        }
      }
      
      for(var i=0;i
      在迭代集合时,无法修改它们。您需要先标记要从集合中删除的项目,然后再删除它们。根据需要,您可以在删除项目之前或之后触发事件。这个代码片段显示了我所涉及的内容

      List itemsTobeRemoved=新列表(); 对于(var i=0;i foreach(itemsTobeRemoved中的变量i=0){ 如果(条件){ 收集、移除(i);
      }

      只有当您可以直接访问收藏项目的“按索引”时,这才可以。我认为第二个选项听起来最好。我只需在更新过程中记录对列表的任何修改,然后在迭代完成后应用它们。请注意,您必须明确“位置”的确切含义这意味着当你做不止一次编辑时——“交换1和2”和“交换2和3”,或者“在A之后移动C”和“删除A”。我通常发现,通过在副本上迭代来生成做正确事情的代码更容易,尽管这可能效率极低。