Iterating a dynamically changing list in C #

I need to iterate through a list (or any enumeration), but I would like to add values ​​to the list during 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 changes in the process?

ADDED

What I want to do is that I iterate over the elements to process something. The fact is that some elements must be decomposed into sub-elements.

 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); } } } } 
+6
source share
7 answers

You cannot, in principle. Anyway, with the foreach . You can use the direct for loop:

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

I personally would try to avoid this in the first place, though - it can be very difficult to speculate about whether you will ever finish, or if you skip paragraphs (if you delete instead of adding or adding before your current position).

+8
source

You can not. You must create a new list and save the values ​​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); } 
+4
source

Use a snapshot instead:

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

The problem is solved! Well, in a way. Elements added during iteration will not be included.

+2
source

No, you cannot iterate over the list and change them at the same iteration. Use a new list instead.

+1
source

Using foreach , you cannot! You can use for-loop, but it is a very bad style to do such things. Such things make your code very error prone, unpredictable, and hard to debug.

0
source

I found that there is a stack in C #. I think I could use the 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); } } } 
0
source

There are answers that claim that you cannot achieve with foreach. This statement is false, all you have to do is write a custom class using a custom enumerator.

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

Now the following code fragment will print 1,2,3,4 and 100 on the screen:

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

But I write this only as a proof of concept. You do not want to do this. If you only add new elements on the flip side, use Queue as others have said. If you will always add new items to the forefront, use Stack. If you need both options, write your own LinkedList class with Dequeue (= Pop), Enqueue, and Push operations, use something like:

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

and all of you are tuned. (You can even write your own custom repeater to use it with foreach, but we destroy the list when we go, so this is contrary to the spirit of enumerations and why bother anyway)

0
source

Source: https://habr.com/ru/post/907354/


All Articles