Error using foreach in a dictionary that contains objects as a value

I am trying to iterate over a dictionary containing objects as a value:

foreach (KeyValuePair<int, CMapPool_Entry> Entry in MapPool) { this.SendConsoleMessage(Entry.Value.Map); } 

Below you can see the CMapPool_Entry class

 public class CMapPool_Entry { public string Map; public string Mode; public int Rounds; public int Index; public int Votes; public bool Nominated; public string Nominator; public CMapPool_Entry(string map, string mode, int rounds, int index, string Nominator_LeaveEmptyStringIfNone) { this.Map = map; this.Mode = mode; this.Rounds = rounds; this.Index = index; // If Nominator isn't empty, set map to nominated if (Nominator_LeaveEmptyStringIfNone != "") { this.Nominated = true; this.Nominator = Nominator_LeaveEmptyStringIfNone; } } public void AddVote() { this.Votes++; } public void RemoveVote() { if (this.Votes > 0) this.Votes--; } } 

Here you can also see the SendConsoleMessage method:

  private void SendConsoleMessage(string message) { this.ExecuteCommand("procon.protected.pluginconsole.write", String.Format("{0}", message)); } 

It seems to me that this will work, I read about how editing the values โ€‹โ€‹from the dictionary inside foreach will give the following error: "The collection has been changed, the enumeration operation cannot be performed."

But why am I getting this error? I am not editing any values, am I just reading them correctly? It works fine if CObject was a string or int instead, but if it is an object, it goes out. What am I doing wrong, what should I do?


EDIT: after further debugging, I noticed that Entry.Key is fine, but as soon as I touch Entry.Value, I get errors. For some reason, I accidentally got two different errors:

  • "The collection has been modified; an enumeration operation cannot be performed.
  • "This key is not in the dictionary.

Any ideas? Or enumerating dictionaries with objects as values โ€‹โ€‹just doesn't work?

+4
source share
2 answers

As stated in the comments, you are modifying the dictionary in another thread while you are trying to read it. You wrote in the comments that you โ€œcopiedโ€ the Dictionary by writing:

 Dictionary<int, CMapPool_Entry> MapPool = this.Votemap_MapPool; 

This does not copy the dictionary, but creates a link to Votemap_MapPool in MapPool , so when you change Votemap_MapPool somewhere in your code when reading MapPool you will get a System.InvalidOperationException with the message that the collection has been changed.

To really copy the dictionary, you need to write:

 Dictionary<int, CMapPool_Entry> MapPool = new Dictionary<int, CMapPool_Entry>(Votemap_MapPool); 

This really creates a new instance of the dictionary with Votemap_MapPool as content, and when Votemap_MapPool changes, MapPool untouched.

+4
source

You cannot change the collection (also as a dictionary library) during foreach processing.

Workaround:

 using System.Linq; foreach (CObject value in ExampleDictionary.Values.ToArray()) { this.SendConsoleMessage(value.SomeVariableInObject); } 
0
source

All Articles