关于C#:通过在循环中添加更多元素来扩展foreach循环

Extending the foreach loop by adding more elements inside the loop

我有这个循环:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
        List<int> list = new List<int>();
        list.Add(1);
        list.Add(2);
        list.Add(3);

        int listCount = list.Count;
        for (int i = 0; i < listCount; i++) // Loop through List with for
        {
            if (i == 2)
            {
                list.Add(666);
                listCount++;
            }
            System.Diagnostics.Debug.Write(list[i]);                
        }

我想知道如何对foreach循环应用相同的逻辑?(在foreach循环中添加更多元素)。

像这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
        List<int> list = new List<int>();
        list.Add(1);
        list.Add(2);
        list.Add(3);

        foreach (int i in list)
        {
            if (i == 2)
            {
                list.Add(666);
                //do something to refresh the foreach loop
            }
            System.Diagnostics.Debug.Write(list[i]);
        }


I am wondering how do I apply the same logic to foreach loop?

不能,也不能。集合不能在foreach循环内修改。

参见:foreach,in(c参考)

If you need to add or remove items from the source collection, use a
for loop.

一种方法是复制列表,然后对原始列表进行如下操作:

1
2
3
4
5
6
7
8
9
foreach (int i in list.ToList())
{
    if (i == 2)
    {
        list.Add(666);
        //do something to refresh the foreach loop
    }
    System.Diagnostics.Debug.Write(list[i]);
}

list.ToList将生成列表的副本,而foreach循环将处理该列表,从而使您免受异常的影响。但这更像是一次黑客攻击,因为您没有在foreach循环中迭代原始列表。


如果要寻找一致的解决方案,可以使用LINQ而不是FOR LOOP或FORACH LOOP(不能在FORACH LOOP中更改集合):

1
2
3
4
5
6
7
8
9
10
11
12
  List<int> list = new List<int>();

  list.Add(1);
  list.Add(2);
  list.Add(3);

  // add required"666" items
  list.AddRange(Enumerable.Repeat(666, list.Count(x => x == 2)));

  // print out all items
  foreach(item in list)
    System.Diagnostics.Debug.Write(item);


不完全是你想做的,但是你可以这样做…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
List<int> list = new List<int>();
list.Add(1);
list.Add(2);
list.Add(3);

List<int> list2 = new List<int>();
list2 = list;

foreach (int i in list)
{
    if (i == 2)
    {
        list2.Add(666);
    }
    System.Diagnostics.Debug.Write(list[i]);
    i++; // increment i
}

list = list2;

您可以编写一个自定义枚举器或集合,允许您在枚举时修改集合。另一方面,你可能应该完全做些别的事情。

我不确定你想做什么,但这对我来说好多了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    List<int> list = new List<int>();
    list.Add(1);
    list.Add(2);
    list.Add(3);

    var outputList = new List<int>();
    foreach (int i in list)
    {
        if (i == 2)
        {
            outputList.Add(666);
            //do something to refresh the foreach loop
        }
        outputList.Add(list[i]);
    }

只需创建一个新列表。尽量不要改变数据结构。那相当脆弱。通常最好从旧数据创建新数据。


不能。foreach循环取决于IEnumerable的行为,结果是在项目迭代期间无法修改集合。每次尝试对集合执行这些类型的修改时,都会收到运行时异常。


是和否,已经给出了两个答案。

通过使用以下语法,可以在foreach循环中从linq修改集合(实际上是list):

1
2
3
4
5
6
7
8
9
10
List<int> list = new List<int>();
list.Add(1);
list.Add(2);
list.Add(3);
list.ForEach(elt => {
     if(elt == 2) {
         list.Add(666);
     }
      System.Diagnostics.Debug.Write(elt);
});

但是要小心…如果在条件内将"2"添加到列表中,则会变为无穷大:)