0

I am trying to update the contents of a C# Dictionary in a foreach loop, when a certain condition is met.

foreach (KeyValuePair<int, Corpus_22_04_2014_StreetTable_Row> entry in id_StreetNameDictionary)
{
    if(something_happens())
    {
         Corpus_22_04_2014_StreetTable_Row r = entry.Value;
         //Modify r
         id_StreetNameDictionary[entry.Key] = r;
    }
}

This throws an InvalidOperationException stating that "Collection was modified; enumeration operation may not execute.". It seems that we are not allowed to modify the contents of a Dictionary in foreach loop.

What can be a possible workaround to that?

Ufuk Can Bicici
  • 3,589
  • 4
  • 28
  • 57
  • http://stackoverflow.com/questions/141088/what-is-the-best-way-to-iterate-over-a-dictionary-in-c see the third answer here – eddie_cat Aug 06 '14 at 16:04
  • 2
    Poor choice on close, Anthony. The suggestion here should be to modify the element's data directly. It isn't the Dictionary that should be modified, but the _Row_ that it contains. – DonBoitnott Aug 06 '14 at 16:05

4 Answers4

4

You can simply use ToList on the dictionary to copy each key-value pair into a list. Then iterate over that list instead of Dictionary:

foreach (var entry in id_StreetNameDictionary.ToList())
{
    if(something_happens())
    {
         Corpus_22_04_2014_StreetTable_Row r = entry.Value;
         //Modify r
         id_StreetNameDictionary[entry.Key] = r;
    }
}
Selman Genç
  • 100,147
  • 13
  • 119
  • 184
2

Create a list of all the keys and iterate that. For example:

foreach (var key in id_StreetNameDictionary.Keys.ToList())
{
    if(something_happens())
    {
         var r = id_StreetNameDictionary[key];
         //Modify r
         id_StreetNameDictionary[key] = r;
    }
}

This will be somewhat more memory efficient than creating a list of KeyValuePair structures from the dictionary.

Jim Mischel
  • 131,090
  • 20
  • 188
  • 351
1

Since it appears you really want to modify the row and not necessarily the Dictionary, then do so directly:

foreach (var entry in id_StreetNameDictionary)
{
    if (something_happens())
    {
        ((Corpus_22_04_2014_StreetTable_Row)entry.Value)["FieldToChange"] = newValue;
        //...repeat for each field to change...you will be altering the row directly, no need to reassign it
    }
}
DonBoitnott
  • 10,787
  • 6
  • 49
  • 68
  • Already tried to directly modify the 'entry.Value' but the compiler says that "Cannot modify because entry.Value is not a variable". I think that the Dictionary entries are meant to be hold as constants. – Ufuk Can Bicici Aug 06 '14 at 16:14
0

Well I use the following workaround. Not very efficient maybe, but it does the work. I declare three dictionaries:

Dictionary<int, Corpus_22_04_2014_StreetTable_Row> id_StreetNameDictionary = new Dictionary<int, Corpus_22_04_2014_StreetTable_Row>();
Dictionary<int, Corpus_22_04_2014_StreetTable_Row> tempDictionary = new Dictionary<int, Corpus_22_04_2014_StreetTable_Row>();
Dictionary<int, Corpus_22_04_2014_StreetTable_Row> swapBuffer;

I completely dump the old dictionary, with all modified and unmodified key/value pairs, into the tempDictionary. Then I swap both dictionaries and clear the unused one:

foreach (var entry in id_StreetNameDictionary)
{
    Corpus_22_04_2014_StreetTable_Row row = id_StreetNameDictionary[entry.Key];
    if (something_happens())
    {

        //Modify row
    }
    tempDictionary.Add(row.id, row);

}

swapBuffer = tempDictionary;
tempDictionary = id_StreetNameDictionary;
id_StreetNameDictionary = swapBuffer;
tempDictionary.Clear();
Ufuk Can Bicici
  • 3,589
  • 4
  • 28
  • 57