迭代在C#中动态修改列表

时间:2012-01-31 20:48:04

标签: c# enumeration

我需要遍历列表(或任何枚举),但我想在迭代过程中将值添加到列表中。

这是一个例子。

public static void RunSnippet()
{
    List<int> hello = new List<int>();

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

    foreach (var x in hello)
    {
        Console.WriteLine(x);
        if (x == 1) {
            hello.Add(100);
        }
    }
}

我希望得到&#34; 1,2,3,100&#34;,但我得到了这个错误。

enter image description here

如何迭代正在更改的列表?

ADDED

我想要完成的是我迭代元素来处理某些事情。问题是需要将一些元素分解为子元素。

public static void RunSnippet()
{
    List<Element> hello = new List<Element>();

    hello.Add(Element); hello.Add(Element); hello.Add(Element);

    foreach (var x in hello)
    {
        List<Element> decomposed;
        decomposed = Decompose(x);
        if (decomposed != null) {
            foreach (var y in decomposed)
            {
                hello.Add(y);
            }
        }
    }
}

7 个答案:

答案 0 :(得分:8)

基本上,你不能。无论如何,没有foreach循环。您可以使用直接for循环:

for (int i = 0; i < hello.Count; i++)
{
    int x = hello[i];
    Console.WriteLine(x);
    if (x == 1) {
        hello.Add(100);
    }
}

我个人会尽量避免在第一时间做这件事 - 你可能会很难说出你是否会完成,或者你是否会跳过项目(如果你要删除而不是添加,或者在当前位置之前添加。)

答案 1 :(得分:4)

你做不到。您应该创建一个新列表并将值存储在那里。

public static void RunSnippet()
{
    List<int> hello = new List<int>();
    List<int> additions = new List<int>();
    hello.Add(1); hello.Add(2); hello.Add(3);

    foreach (var x in hello)
    {
        Console.WriteLine(x);
        if (x == 1) {
            additions.Add(100);
        }
    }

    hello.AddRange(additions);
}

答案 2 :(得分:2)

改为使用快照:

foreach (var x in hello.ToArray())
{
    // whatever here
}

问题解决了!好吧,在某种程度上。迭代期间添加的项目不会包含在内。

答案 3 :(得分:1)

不,您不能迭代列表并在同一次迭代中修改它们。改为使用新列表。

答案 4 :(得分:0)

使用foreach你不能!你可以使用for循环,但做这样的事情是非常糟糕的风格。这样的事情会使您的代码非常容易出错,不可预测且难以调试。

答案 5 :(得分:0)

我发现C#中有堆栈。我想我可以使用堆栈。

public static void RunSnippet()
{
    Stack<int> hello = new Stack<int>();
    hello.Push(1); hello.Push(2); hello.Push(3);

    while (hello.Count > 0)
    {
        int x = hello.Pop();
        Console.WriteLine(x);
        if (x == 1) {
            hello.Push(100);
        }
    }
}

答案 6 :(得分:0)

有些答案声称你想要的东西无法用foreach实现。这种说法是错误的,您需要做的就是使用自定义枚举器编写自定义类。

   public class CustomList : IEnumerable<int>
   {
      readonly List<int> list = new List<int>{1,2,3,4};
      private int now = 0;

      public void Add(int n)
      {
         list.Add(n);
      }

      public IEnumerator<int> GetEnumerator()
      {
         while (now<list.Count)
         {
            yield return list[now];
            now++;
         }
      }

      IEnumerator IEnumerable.GetEnumerator()
      {
         return GetEnumerator();
      }
   }

现在,以下代码将1,2,3,4和100打印到屏幕上:

 var list = new CustomList();
 foreach (int n in list)
 {
    if(n==1)
       list.Add(100);
    Console.WriteLine(n);
 }

但我写这只是为了概念证明。你不想这样做。如果您只在背面添加新项目,请使用其他人所说的队列。如果您始终在前面添加新项目,请使用Stack。如果您需要两者,使用Dequeue(= Pop),Enqueue和Push操作编写自定义LinkedList类,请使用以下内容:

while(list.notEmpty()) 
  var item = list.Dequeue();
  //bla bla

你们都已经准备好了。 (您甚至可以再次编写一个自定义枚举器,与foreach一起使用,但我们正在破坏列表,因此它违反了Enumerations的精神,以及为什么在任何情况下都会烦恼)