Ric*_*rdo 78 c# collections enumeration exception
我正在尝试删除一个项目ArrayList,我得到这个例外:
Collection was modified; enumeration operation may not execute.
有任何想法吗?
Mar*_*ell 191
您正在删除该项目foreach,是吗?简单地说,你不能.这里有一些常见的选择:
List<T>和RemoveAll谓词按索引向后迭代,删除匹配的项目
for(int i = list.Count - 1; i >= 0; i--) {
if({some test}) list.RemoveAt(i);
}
Run Code Online (Sandbox Code Playgroud)使用foreach,并将匹配的项目放入第二个列表; 现在枚举第二个列表并从第一个列表中删除这些项目(如果你看到我的意思)
Wil*_*ill 24
这是一个例子(抱歉任何错别字)
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);
}
Run Code Online (Sandbox Code Playgroud)
或者,如果您使用3.5,Linq使第一点更容易:
itemsToRemove = originalArrayList
.Where(item => ...)
.ToArray();
foreach (var item in itemsToRemove) {
originalArrayList.Remove(item);
}
Run Code Online (Sandbox Code Playgroud)
将"..."替换为确定是否应删除项目的条件.
我喜欢使用循环向后迭代for,但与之相比,这可能会变得乏味foreach.我喜欢的一个解决方案是创建一个向后遍历列表的枚举器.您可以在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];
}
}
Run Code Online (Sandbox Code Playgroud)
实现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];
}
}
Run Code Online (Sandbox Code Playgroud)
下面的示例使用枚举器从a中删除所有偶数整数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);
}
Run Code Online (Sandbox Code Playgroud)
不要修改循环遍历列表的循环内的列表.
相反,使用a for()或while()带索引,在列表中向后移动.(这样可以在不获取无效索引的情况下删除内容.)
var foo = new List<Bar>();
for(int i = foo.Count-1; i >= 0; --i)
{
var item = foo[i];
// do something with item
}
Run Code Online (Sandbox Code Playgroud)
我错过了什么吗?如果我错了,有人纠正我。
list.RemoveAll(s => s.Name == "Fred");
Run Code Online (Sandbox Code Playgroud)