在 C# 中使用 foreach 循环时修改 Collection

发布于 2024-07-26 20:43:57 字数 799 浏览 6 评论 0原文

基本上,我想在 foreach 循环内从列表中删除一个项目。 我知道使用 for 循环时这是可能的,但出于其他目的,我想知道使用 foreach 循环是否可以实现这一点。

在 python 中,我们可以通过执行以下操作来实现此目的:

a = [1, 2, 3, 4, 5, 6, 7, 8, 9]

for i in a:
    print i

    if i == 1:
        a.pop(1)

这给出了以下输出

>>>1
3
4
5
6
7
8
9

但是,当在 c# 中执行类似操作时,我得到一个 InvalidOperationException,我想知道是否有一种方法可以解决这个问题,而不仅仅是简单地使用for 循环

我在抛出异常时使用的c#代码:

static void Main(string[] args)
  {
  List<string> MyList = new List<string>(new string[] { "1", "2", "3", "4", "5", "6", "7", "8", "9"});

  foreach (string Item in MyList)
    {
    if (MyList.IndexOf(Item) == 0)
      {
      MyList.RemoveAt(1);
      }

    Console.WriteLine(Item);
    }
  }

提前致谢

Basically, I would like to remove an item from a list whilst inside the foreach loop. I know that this is possible when using a for loop, but for other purposes, I would like to know if this is achievable using a foreach loop.

In python we can achieve this by doing the following:

a = [1, 2, 3, 4, 5, 6, 7, 8, 9]

for i in a:
    print i

    if i == 1:
        a.pop(1)

This gives the following Output

>>>1
3
4
5
6
7
8
9

But when doing something similar in c#, I get an InvalidOperationException, I was wondering if there was a way of getting around this, without just simply using a for loop.

The code in c# that I used when the exception was thrown:

static void Main(string[] args)
  {
  List<string> MyList = new List<string>(new string[] { "1", "2", "3", "4", "5", "6", "7", "8", "9"});

  foreach (string Item in MyList)
    {
    if (MyList.IndexOf(Item) == 0)
      {
      MyList.RemoveAt(1);
      }

    Console.WriteLine(Item);
    }
  }

Thanks in advance

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

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

发布评论

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

评论(3

小草泠泠 2024-08-02 20:43:57

你不能这样做。 来自 IEnumerator的文档:

只要
该集合保持不变。 如果
对集合进行更改,
如添加、修改、删除等
元素,枚举数是
不可恢复地失效及其
行为未定义。

替代方法是:

  • 建立一个新的要删除的项目列表,然后将它们全部删除
  • 使用正常的“for”循环并确保小心不要两次遍历相同的元素或遗漏任何元素。 (您已经说过您不想这样做,但是您尝试做的事情是行不通的。)
  • 构建一个仅包含您想要保留的元素的新集合

最后一个替代方案是 LINQ-就像解决方案一样,您通常会在其中编写:(

var newList = oldList.Where(x => ShouldBeRetained(x)).ToList();

当然,其中 ShouldBeRetained 是您想要的任何逻辑。)仅当您确实想要时,才需要调用 ToList()它在一个列表中。 这会产生更具声明性的代码,通常更容易阅读。 我无法轻易猜测您原来的循环的用途(目前看起来很奇怪),而如果您可以纯粹用项目来表达逻辑,那么它会更清晰。

You can't do this. From the docs for IEnumerator<T>:

An enumerator remains valid as long as
the collection remains unchanged. If
changes are made to the collection,
such as adding, modifying, or deleting
elements, the enumerator is
irrecoverably invalidated and its
behavior is undefined.

Alternatives are:

  • Build up a new list of items to remove, then remove them all afterwards
  • Use a normal "for" loop and make sure you're careful about not going over the same element twice or missing any out. (You've said you don't want to do this, but what you're trying to do just won't work.)
  • Build a new collection containing only the elements you want to retain

The last of these alternatives is the LINQ-like solution, where you'd typically write:

var newList = oldList.Where(x => ShouldBeRetained(x)).ToList();

(Where ShouldBeRetained is whatever logic you want, of course.) The call to ToList() is only necessary if you actually want it in a list. This leads to more declarative code which is often easier to read. I can't easily guess what your original loop is meant to do (it seems pretty odd at the moment) whereas if you can express the logic purely in terms of the item, it can be a lot clearer.

预谋 2024-08-02 20:43:57

如果您需要的只是删除满足条件的所有项目,您可以使用 List< T>.RemoveAll 方法:

List<string> MyList = new List<string>(new string[] { "1", "2", "3", "4", "5", "6", "7", "8", "9" });
MyList.RemoveAll(item => item == "1");

请注意,这会修改初始列表。

If all you need is to remove all items that satisfy a condition you could use the List<T>.RemoveAll method:

List<string> MyList = new List<string>(new string[] { "1", "2", "3", "4", "5", "6", "7", "8", "9" });
MyList.RemoveAll(item => item == "1");

Note that this modifies the initial list.

-柠檬树下少年和吉他 2024-08-02 20:43:57

在对集合使用 foreach 循环时,绝对不能以任何方式更改集合。

您可以使用 for 循环并自行管理索引,或者制作集合的副本,并在循环原始集合时,从副本中删除与原始集合中的项目相同的项目。

在这两种情况下,它都不是那么清晰或方便:)。

You definitely may not change a collection in any way when using a foreach loop on it.

You can use a for loop and manage the index for yourself or make a copy of the collection and as you are looping the original, remove items from the copy that equal the item in the original.

In both cases it's not quite as clear or convenient :).

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