集合已修改; ArrayList 中不能执行枚举操作

发布于 2024-08-16 19:41:07 字数 101 浏览 4 评论 0原文

我试图从 ArrayList 中删除一个项目,但出现此异常:
集合已修改;枚举操作可能无法执行。

有什么想法吗?

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

Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

稀香 2024-08-23 19:41:07

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

  • 使用 ListRemoveAll 以及谓词
  • 按索引向后迭代,删除匹配项

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

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

  • use List<T> and RemoveAll with 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)

圈圈圆圆圈圈 2024-08-23 19:41:07

这是一个示例(对于任何拼写错误,我们深表歉意)

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

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

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:

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

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

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

一萌ing 2024-08-23 19:41:07

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

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

伴我老 2024-08-23 19:41:07

我喜欢使用 for 循环向后迭代,但这与 foreach 相比可能会变得乏味。我喜欢的一种解决方案是创建一个向后遍历列表的枚举器。您可以将其实现为 ArrayListList 上的扩展方法。 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 的实现类似。

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

I like to iterate backward using a for loop, 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 ArrayList or List<T>. The implementation for ArrayList is below.

    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.

    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 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);
    }
夜深人未静 2024-08-23 19:41:07

不要在迭代列表的循环内修改列表。

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

var foo = new List<Bar>();

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

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.)

var foo = new List<Bar>();

for(int i = foo.Count-1; i >= 0; --i)
{
  var item = foo[i];
  // do something with item
}
蓝海似她心 2024-08-23 19:41:07

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

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

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

list.RemoveAll(s => s.Name == "Fred");
何其悲哀 2024-08-23 19:41:07

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

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

紅太極 2024-08-23 19:41:07

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

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

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

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

例如

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

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.

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;
}        
嗫嚅 2024-08-23 19:41:07

使用 ArrayList 你也可以尝试这样

ArrayList arraylist = ... // myobject data list

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

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

using ArrayList also you can try like this

ArrayList arraylist = ... // myobject data list

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

foreach (var item in temp)
{
      if (...)
         arraylist.Remove(item);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文