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一个向后遍历列表的枚举器。 您可以在ArrayList
或List<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); }