Yogesh
Yogesh

Reputation: 3076

using yield in c# over a collection still I can't update my collection

 static List<int> numbers = new List<int>();
    static void Main(string[] args)
    {

        foreach(var number in GetNumbers())
        {
            if (number == 1)
            {
                Thread t = new Thread(() => 
                {
                    numbers.Add(234567);
                });
                t.Start();
            }
            Console.WriteLine(number);
        }

    }



    public static IEnumerable<int> GetNumbers()
    {

        for(int i =0; i <=10;i++)
        {
            numbers.Add(i);
        }
        foreach (var number in numbers)
        {
            yield return number;
        }            

    }

In the above example, I was iterating over collection using yield and added an item into the collection to get the updated number.

I understand modifying a collection which we are iterating throws a collection modified exception but with IEnumerable, I get deferred execution and I should be able to add to the main collection as yield would return data one by one.

I understand, removing an item could be problematic but adding an item to iterating collection should not be problem. However,if it is not allowed as what I have seen in above example(even it is deferred execution), what if I have situation like this:

"There is a large collection and so many consumers are iterating over it using IEnumerable and yield. They take each item, do some processing with this item.

and If there is any new item added into main list or collection, then client should get the latest item too.

Upvotes: 0

Views: 381

Answers (1)

mjwills
mjwills

Reputation: 23975

Even though you are using yield, you are using it inside a foreach.

The docs state:

It is safe to perform multiple read operations on a List, but issues can occur if the collection is modified while it’s being read.

This is the fundamental issue here - you are reading the collection (as evidenced by the foreach) while writing to it. That just isn't allowed.

This may be worth reading - https://social.msdn.microsoft.com/Forums/vstudio/en-US/a90c87be-9553-4d48-9892-d482ee325f02/why-cant-change-value-in-foreach?forum=csharpgeneral

You likely want to consider using ConcurrentBag, ConcurrentQueue or ConcurrentStack as alternatives.

Upvotes: 3

Related Questions