0

Here is the code

List<Vector2Int> startPos = new();
        startPos.Add(new(5, 5));
        for (int i = 0; i < 2; i++)
        {
            var something = FloodFill(startPos);
            foreach (KeyValuePair<Vector2Int, string> kv in something)
            {
                Debug.Log(kv.Key);
            }
            startPos.Clear();
            List<Vector2Int> vector2Ints = new(something.Keys);
            startPos = vector2Ints;
        }

The above code is the code that I used and it's showing an error. Perhaps there is an error in the above part but for reference, I am also attaching the Floodfill function that I have written.

Dictionary<Vector2Int, string> FloodFill(List<Vector2Int> startPos)
    {
        Dictionary<Vector2Int, string> returnList = new();
        foreach (Vector2Int pos in startPos)
        {
            returnList.Add(pos, "Anything");
        }
        
        List<Vector2Int> nextIterationList = new(startPos);
        List<Vector2Int> tempList = new();
        foreach (Vector2Int point in nextIterationList)
        {
            for (int m = 0; m < 3; m++)
            {
                tempList.Add(new(point.x - 1, point.y + (m - 1)));
                tempList.Add(new(point.x + 1, point.y + (m - 1)));
                if (m == 1)
                {
                    continue;
                }
                tempList.Add(new(point.x, point.y + (m - 1)));
            }
            foreach (Vector2Int dot in tempList)
            {
                if (returnList.ContainsKey(dot))
                {
                    tempList.Remove(dot);
                }
                else
                {
                    returnList.Add(dot, "Anything");
                }
            }
        }
        return returnList;
    }

The error that I am receiving is Collection was modified; enumeration operation may not execute. System.Collections.Generic.List1+Enumerator[T].MoveNextRare () (at <31c0f51ac5a24a22ba784db24f4ba023>:0) System.Collections.Generic.List1+Enumerator[T].MoveNext () (at <31c0f51ac5a24a22ba784db24f4ba023>:0)

3 Answers3

1

What's happening is that you alter the collection while iterating over it.

It makes sense this is not allowed, because, for example if you're sorting an array and insert elements while doing so this can lead to some confusing results or is hard/inconvenient to implement.

Looking at this:

foreach (Vector2Int dot in tempList)
{
      if (returnList.ContainsKey(dot))
      {
          tempList.Remove(dot);
      }
      else
      {
          returnList.Add(dot, "Anything");
      }
}

You are removing from tempList while iterating it - effectively shorting the list, so; what to do with the enumerator position? Hence the error.

This could have been implemented but they choose not to.

As alternative you an use a reversed indexer for to remove the element while enumerating the collection.

for (var i = tempList.Length - 1; i >= 0; i--)
Stefan
  • 17,448
  • 11
  • 60
  • 79
1

Exception reads something like this:

collection was modified after the enumerator was instantiated

it simply states that within your loop you are modifying the collection

// this creates enumerator you can thing
// its a thing that enables foreach loop
foreach (Vector2Int dot in tempList)
        {
            if (returnList.ContainsKey(dot))
            {
// here you are modifying the list that you are iterating over
// this is not allowed
                tempList.Remove(dot);
            }
            else
            {
                returnList.Add(dot, "Anything");
            }
        }

simply do not modify the list that you are looping over either by creating yourself a copy

foreach(Vector2Int dot in temList.ToArray())

not the geretest for game dev as it allocates memory

or you can change to for loop, but you need to manage the index

for(var i = 0 ; i < tempList.Count ; i++)
{
  var dot = tempList[i];

and decrement i on item removal

if (returnList.ContainsKey(dot))
            {

                tempList.RemoveAt(i);
                i--;
            }

or you can change to for loop descending (thanks @Stefan for pointing this out)

 for(var i = 0 ; i < tempList.Count ; i--)
 {
      var dot = tempList[i];

and just do what you are doing just in reveres. With this approach index will just work yet you must make sure that changing the order of execution will not influence the result this might happen if your list is sorted or somehow order is important.

Rafal
  • 12,391
  • 32
  • 54
  • Typically this is done by a reverse for - `for (var i = tempList.Length - 1; i >= 0; i--)` that way you don't need to correct when removing the element. Otherwise, nice answer – Stefan Jan 31 '22 at 13:53
  • @Stefan yes its another way of doing this, in this case you change order of the loop and for some applications it makes no difference and for other order might be important. – Rafal Jan 31 '22 at 17:39