在C#中使用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);
}
}
提前谢谢你们!
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()
只有在你真的想要一个列表的时候才需要。这种方式的代码更具描述性,通常更容易阅读。我现在很难猜测你原来的循环是想做什么(看起来有点奇怪),而如果你能把逻辑完全用元素来表达,那就会清晰很多。