Given the following code, I’m curious to know how to avoid the following exception
System.InvalidOperationException was unhandled
Message=Collection was modified; enumeration operation may not execute.
Source=mscorlib
StackTrace:
at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
at System.Collections.Generic.List`1.Enumerator.MoveNextRare()
at System.Collections.Generic.List`1.Enumerator.MoveNext()
at PBV.Program.Main(String[] args) in C:\Documents and Settings\tmohojft\Local Settings\Application Data\Temporary Projects\PBV\Program.cs:line 39
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:
CODE:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace PBV
{
class Program
{
struct structItem
{
public int y { get; set; }
public int z { get; set; }
}
struct testStruct
{
public int x { get; set; }
public List<structItem> items { get; set; }
}
static void Main(string[] args)
{
testStruct a = new testStruct();
structItem b = new structItem();
for (byte i = 0; i <= 10; i++) {
b.y = i;
b.z = i * 2;
a.items = new List<structItem>();
a.items.Add(b);
}
testStruct c = new testStruct();
c = a;
int counter = 0;
//exception thrown on line below
foreach (var item in a.items) {
structItem d = item;
d.z = 3;
c.items[counter] = d;
counter++;
}
a = c;
}
}
}
I originally tried to simply put the following in the second foreach:
item.z = 3;
But that caused the following error:
Cannot modify members of "item" because it is a "foreach iteration"
I tried to create a temporary object in order to be able to modify the struct data inside the foreach, but I recieve the exception above. My best guess is because my temporary struct is saving a reference to the original struct rather than the value itself – which is leading my original struct to be updated when my temporary struct is.
So my question is:
How do I pass this struct by value rather than reference? Or is there an entirely different way to get around this issue?
Thanks in advance for the help.
EDIT: Thanks for all the answers guys. I’m aware that the list is a reference type, but does that make it impossible to pass by value instead of reference then?
I’m a little confused by what your example code is trying to do, but I think perhaps part of your confusion may be that when you set
c = a, you expect it to make a copy of the list. It does not. While the structure itself is a value type, the items property it contains is not. List<> is a reference type, so when you setc = a, it copies thatitemsreference to c. So, when you enter the loop, both a and c contain a reference to the same list object. Therefore, when you modify the list while you are enumerating through it, it will always fail.A simple way to avoid this is to iterate through a static copy of your list: