C# 集合被修改;枚举操作可能不会在 ArrayList 中执行

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2024179/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 22:47:41  来源:igfitidea点击:

Collection was modified; enumeration operation may not execute in ArrayList

c#exceptioncollectionsenumeration

提问by Ricardo

I'm trying to remove an item from an ArrayListand I get this Exception:
Collection was modified; enumeration operation may not execute.

我正在尝试从 an 中删除一个项目,但出现ArrayList此异常:
Collection was modified; enumeration operation may not execute.

Any ideas?

有任何想法吗?

采纳答案by Marc Gravell

You are removing the item during a foreach, yes? Simply, you can't. There are a few common options here:

您是在 a 期间删除该项目foreach,是吗?简单地说,你不能。这里有一些常见的选项:

  • use List<T>and RemoveAllwith a predicate
  • iterate backwards by index, removing matching items

    for(int i = list.Count - 1; i >= 0; i--) {
        if({some test}) list.RemoveAt(i);
    }
    
  • use foreach, and put matching items into a second list; now enumerate the second list and remove those items from the first (if you see what I mean)

  • 使用List<T>RemoveAll带谓词
  • 按索引向后迭代,删除匹配项

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

回答by 3Dave

Don't modify the list inside of a loop which iterates through the list.

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

Instead, use a for()or while()with an index, going backwards through the list. (This will let you delete things without getting an invalid index.)

相反,使用带有索引的for()while(),向后遍历列表。(这将使您可以删除内容而不会获得无效索引。)

var foo = new List<Bar>();

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

回答by Seva Alekseyev

Instead of foreach(), use a for() loop with a numeric index.

使用带有数字索引的 for() 循环代替 foreach()。

回答by ozczecho

One way is to add the item(s) to be deleted to a new list. Then go through and delete those items.

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

回答by Will

Here's an example (sorry for any typos)

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

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

OR if you're using 3.5, Linq makes the first bit easier:

或者,如果您使用的是 3.5,Linq 会使第一个更容易:

itemsToRemove = originalArrayList
  .Where(item => ...)
  .ToArray();

foreach (var item in itemsToRemove) {
  originalArrayList.Remove(item);
}

Replace "..." with your condition that determines if item should be removed.

将“...”替换为确定是否应删除项目的条件。

回答by Joe B

I like to iterate backward using a forloop, but this can get tedious compared to foreach. One solution I like is to create an enumerator that traverses the list backward. You can implement this as an extension method on ArrayListor List<T>. The implementation for ArrayListis below.

我喜欢使用循环向后迭代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];
        }
    }

The implementation for List<T>is similar.

的实现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];
        }
    }

The example below uses the enumerator to remove all even integers from an ArrayList.

下面的示例使用枚举器从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);
    }

回答by Brian Wells

I agree with several of the points I've read in this post and I've incorporated them into my solution to solve the exact same issue as the original posting.

我同意我在这篇文章中读到的一些观点,并且我已将它们合并到我的解决方案中,以解决与原始帖子完全相同的问题。

That said, the comments I appreciated are:

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

  • "unless you are using .NET 1.0 or 1.1, use List<T>instead of ArrayList. "

  • "Also, add the item(s) to be deleted to a new list. Then go through and delete those items." .. in my case I just created a new List and the populated it with the valid data values.

  • “除非你正在使用.NET 1.0或1.1,使用List<T>替代ArrayList。”

  • “另外,将要删除的项目添加到新列表中。然后通过并删除这些项目。” .. 就我而言,我刚刚创建了一个新列表,并用有效数据值填充了它。

e.g.

例如

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

回答by KevinDeus

Am I missing something? Somebody correct me if I'm wrong.

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

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

回答by Nikson Kanti Paul

using ArrayListalso you can try like this

使用ArrayList你也可以尝试这样

ArrayList arraylist = ... // myobject data list

ArrayList temp = (ArrayList)arraylist.Clone();

foreach (var item in temp)
{
      if (...)
         arraylist.Remove(item);
}