在c#中使用foreach循环时修改集合
基本上,我想在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循环 。
我抛出exception时使用的c#代码:
static void Main(string[] args) { List MyList = new List(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); } }
提前致谢
你不能这样做。 来自IEnumerator
的文档:
只要集合保持不变,枚举器仍然有效。 如果对集合进行了更改(例如添加,修改或删除元素),则枚举数将无法恢复,并且其行为未定义。
替代方案是:
- 建立要删除的新项目列表,然后将其全部删除
- 使用正常的“for”循环,并确保你小心不要重复两次相同的元素或遗漏任何一个元素。 (你已经说过你不想这样做,但你想做的事情是行不通的。)
- 构建一个仅包含要保留的元素的新集合
这些替代方案中的最后一个是类似LINQ的解决方案,您通常会在其中编写:
var newList = oldList.Where(x => ShouldBeRetained(x)).ToList();
(当然, ShouldBeRetained
是你想要的任何逻辑。)只有你真正想要它在列表中时才需要调用ToList()
。 这导致更多的声明性代码,通常更容易阅读。 我不能轻易猜出你的原始循环是做什么的(此刻看起来很奇怪),而如果你可以纯粹根据项目来表达逻辑,那么它可以更加清晰。
如果您只需删除满足条件的所有项目,则可以使用List
List MyList = new List (new string[] { "1", "2", "3", "4", "5", "6", "7", "8", "9" }); MyList.RemoveAll(item => item == "1");
请注意,这会修改初始列表。
在使用foreach循环时,绝对不能以任何方式更改集合。
您可以使用for循环并自行管理索引或制作集合的副本,并在循环原始时,从副本中删除与原始项目相同的项目。
在这两种情况下,它都不是那么清楚或方便:)。