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

8 投票
3 回答
3548 浏览
提问于 2025-04-15 12:53

基本上,我想在遍历一个列表的时候,删除其中的一个项目。我知道在使用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);
    }
  }

提前谢谢你们!

3 个回答

1

在使用foreach循环遍历一个集合时,你绝对不能以任何方式修改这个集合。

你可以使用for循环,自行管理索引,或者先复制一份集合,在遍历原集合的时候,从复制的那份中删除与原集合相同的项。

不过这两种方法都没有foreach那么简单明了哦 :).

6

如果你只想删除所有满足某个条件的项目,可以使用 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");

请注意,这个方法会直接修改原来的列表。

26

你不能这样做。根据关于 IEnumerator<T> 的说明:

一个枚举器(也就是用来遍历集合的工具)只要集合没有变化,它就一直有效。如果对集合进行了修改,比如添加、修改或删除元素,这个枚举器就会变得无效,之后的行为就无法预测了。

可以考虑的替代方案有:

  • 先建立一个新的要删除的项目列表,然后再一次性删除它们。
  • 使用普通的“for”循环,确保小心不要重复处理同一个元素,也不要漏掉任何元素。(你说过不想这样做,但你想要的做法就是行不通。)
  • 建立一个新的集合,只包含你想保留的元素。

最后一个替代方案类似于LINQ的写法,通常你会这样写:

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

(其中 ShouldBeRetained 是你想要的逻辑。)调用 ToList() 只有在你真的想要一个列表的时候才需要。这种方式的代码更具描述性,通常更容易阅读。我现在很难猜测你原来的循环是想做什么(看起来有点奇怪),而如果你能把逻辑完全用元素来表达,那就会清晰很多。

撰写回答