Dan
Dan

Reputation: 45

Unexpected 'Collection was modified; enumeration operation may not execute.' exception for List enumeration, despite List not being modified

I'm getting the exception "System.InvalidOperationException: 'Collection was modified; enumeration operation may not execute.'" in my code. I understand what the exception is, but what I can't understand is why I'm getting it based off of my code.

public static void DiffCircles(Circle original, Circle toSubtract)
        {
            List<Vector2> originalAreaCopy = original.area;
            foreach(Vector2 oArea in original.area) -- **Exception occurs here on the second iteration**
            {
                foreach(Vector2 tsArea in toSubtract.area)
                {
                    if(oArea.X == tsArea.X && oArea.Y == tsArea.Y)
                    {
                        originalAreaCopy.Remove(originalAreaCopy[original.area.IndexOf(oArea)]);
                    }
                }
            }
            original.area = originalAreaCopy;
        }

Originally I had been removing the overlapping vector2s by doing original.area.Remove(oArea) at the if statement. I got the exception, and then looked it up, and realized why I was getting it. So I figured if I made a copy list, removed the overlap from the copy list, then just set the original list equal to the copy list after the end of the nested loops, I would be fine. However I still get the exception, surprisingly.

Could anyone explain why I'm still getting this error? I'm no longer modifying the collection during the loop, so I thought this would work, but for some reason it doesn't...

Thanks!

Upvotes: 1

Views: 8912

Answers (1)

Lasse V. Karlsen
Lasse V. Karlsen

Reputation: 391406

The confusion you have stems from this assumption:

So I figured if I made a copy list

List<Vector2> originalAreaCopy = original.area;

This does not in fact make a copy of the list, it makes a copy of the reference to it. Reference type variables only store the reference to the object so in this case, you now have two variables both referencing the same object, the list, original.area and originalAreaCopy.

So when you later remove an object from the list, through originalAreaCopy, it's still the exact same list you're iterating over, through original.area. However, you still only have one list object.

In order to make a copy of the list and not just the reference to it, the easiest is probably just to do this:

List<Vector2> originalAreaCopy = original.area.ToList();

This will construct a new list containing all the elements in original.area, so now original.area and originalAreaCopy actually references two distinct list objects.

Upvotes: 3

Related Questions