collections被修改; 枚举操作可能不会在ArrayList中执行

我试图从一个ArrayList删除一个项目,我得到这个例外:
Collection was modified; enumeration operation may not execute.

有任何想法吗?

你在foreach中删除该项目,是吗? 简而言之,你不能。 这里有几个常见的选项:

  • 使用List<T>RemoveAll与谓词
  • 通过索引向后迭代,删除匹配的项目

     for(int i = list.Count - 1; i >= 0; i--) { if({some test}) list.RemoveAt(i); } 
  • 使用foreach ,并将匹配的项目放入第二个列表中; 现在列举第二个列表,并从第一个列表中删除这些项目(如果你明白我的意思)

这里是一个例子(抱歉任何错别字)

 var itemsToRemove = new ArrayList(); // should use generic List if you can foreach (var item in originalArrayList) { if (...) { itemsToRemove.Add(item); } } foreach (var item in itemsToRemove) { originalArrayList.Remove(item); } 

或者如果你使用3.5,Linq使得第一个比较容易:

 itemsToRemove = originalArrayList .Where(item => ...) .ToArray(); foreach (var item in itemsToRemove) { originalArrayList.Remove(item); } 

将“…”replace为确定是否应删除项目的条件。

一种方法是将要删除的项目添加到新列表中。 然后通过并删除这些项目。

我喜欢用for循环向后迭代,但与foreach相比,这会变得乏味。 我喜欢的一个解决scheme是创build一个向后遍历列表的枚举器。 您可以在ArrayListList<T>上将其实现为扩展方法。 下面是ArrayList的实现。

  public static IEnumerable GetRemoveSafeEnumerator(this ArrayList list) { for (int i = list.Count - 1; i >= 0; i--) { // Reset the value of i if it is invalid. // This occurs when more than one item // is removed from the list during the enumeration. if (i >= list.Count) { if (list.Count == 0) yield break; i = list.Count - 1; } yield return list[i]; } } 

List<T>的实现类似。

  public static IEnumerable<T> GetRemoveSafeEnumerator<T>(this List<T> list) { for (int i = list.Count - 1; i >= 0; i--) { // Reset the value of i if it is invalid. // This occurs when more than one item // is removed from the list during the enumeration. if (i >= list.Count) { if (list.Count == 0) yield break; i = list.Count - 1; } yield return list[i]; } } 

下面的示例使用枚举器从ArrayList移除所有偶数整数。

  ArrayList list = new ArrayList() {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; foreach (int item in list.GetRemoveSafeEnumerator()) { if (item % 2 == 0) list.Remove(item); } 

不要修改遍历列表的循环内的列表。

相反,使用for()while()与索引,向后遍历列表。 (这会让你删除东西而不会收到一个无效的索引。)

 var foo = new List<Bar>(); for(int i = foo.Count-1; i >= 0; --i) { var item = foo[i]; // do something with item } 

我错过了什么吗? 有人纠正我,如果我错了。

 list.RemoveAll(s => s.Name == "Fred"); 

而不是foreach(),使用带有数字索引的for()循环。

我同意我在这篇文章中阅读过的几个观点,并将它们合并到我的解决scheme中,以解决与原始发布完全相同的问题。

这就是说,我赞赏的评论是:

  • “除非您使用.NET 1.0或1.1,否则使用List<T>而不是ArrayList 。”

  • “另外,将要删除的项目添加到新列表中,然后通过并删除这些项目。” ..在我的情况下,我刚刚创build了一个新的列表,并填充有效的数据值。

例如

 private List<string> managedLocationIDList = new List<string>(); string managedLocationIDs = ";1321;1235;;" // user input, should be semicolon seperated list of values managedLocationIDList.AddRange(managedLocationIDs.Split(new char[] { ';' })); List<string> checkLocationIDs = new List<string>(); // Remove any duplicate ID's and cleanup the string holding the list if ID's Functions helper = new Functions(); checkLocationIDs = helper.ParseList(managedLocationIDList); ... public List<string> ParseList(List<string> checkList) { List<string> verifiedList = new List<string>(); foreach (string listItem in checkList) if (!verifiedList.Contains(listItem.Trim()) && listItem != string.Empty) verifiedList.Add(listItem.Trim()); verifiedList.Sort(); return verifiedList; } 

使用ArrayList也可以尝试这样

 ArrayList arraylist = ... // myobject data list ArrayList temp = (ArrayList)arraylist.Clone(); foreach (var item in temp) { if (...) arraylist.Remove(item); }