Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Iterating over dynamically modifying list in C#

Tags:

c#

enumeration

I need to iterate over a list (or whatever enumeration), but I'd like to add values into the list in the course of the iteration.

This is an example.

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);
        }
    }
}

I expect to get "1,2,3,100", but instead I got this error.

enter image description here

How can I iterate over a list that is changing in the process?

ADDED

What I want to accomplish is that I iterate over elements to process something. The thing is that some of the elements needs to be decomposed into sub elements on and on.

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);
            }
        }
    }
}
like image 376
prosseek Avatar asked Jan 31 '12 20:01

prosseek


5 Answers

You can't, basically. Not with a foreach loop, anyway. You can use a straight for loop:

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

I would personally try to avoid doing it in the first place though - it can get very hard to reason about whether you'll ever complete, or if you'll skip items (if you're removing instead of adding, or adding before your current position).

like image 180
Jon Skeet Avatar answered Nov 18 '22 00:11

Jon Skeet


You can't. You should create a new list and store the values in there.

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);
}
like image 41
Daniel A. White Avatar answered Nov 17 '22 23:11

Daniel A. White


Use a snapshot of it instead:

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

Problem solved! Well, in a way. Items added during iteration would not be included.

like image 3
Kieren Johnstone Avatar answered Nov 18 '22 00:11

Kieren Johnstone


No, you can't iterate over a list and modify them in the same iteration. Use a new list instead.

like image 1
Pyth0n Avatar answered Nov 17 '22 23:11

Pyth0n


I found that there is stack in C#. I guess I could use stack.

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);
        }
    }
}
like image 1
prosseek Avatar answered Nov 17 '22 23:11

prosseek