关于C#:在foreach循环中修改字典的内容

Modifying the contents of a Dictionary in foreach loop

当满足某个条件时,我正在尝试在foreach循环中更新C字典的内容。

1
2
3
4
5
6
7
8
9
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;
    }
}

这将引发一个InvalidOperationException,声明"集合已修改;枚举操作可能未执行"。似乎不允许在foreach循环中修改字典的内容。

有什么办法可以解决这个问题?


您只需在字典上使用ToList就可以将每个键值对复制到一个列表中。然后迭代该列表而不是Dictionary

1
2
3
4
5
6
7
8
9
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;
    }
}

创建所有键的列表并迭代。例如:

1
2
3
4
5
6
7
8
9
foreach (var key in id_StreetNameDictionary.Keys.ToList())
{
    if(something_happens())
    {
         var r = id_StreetNameDictionary[key];
         //Modify r
         id_StreetNameDictionary[key] = r;
    }
}

这将比从字典中创建一个KeyValuePair结构列表更节省内存。


由于您似乎真的想修改行,而不一定要修改Dictionary,那么直接修改:

1
2
3
4
5
6
7
8
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
    }
}


我使用下面的解决方法。也许效率不高,但它起作用。我申报了三本词典:

1
2
3
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;

我将所有修改过和未修改过的键/值对的旧字典完全转储到tempdictionary中。然后我交换两个字典并清除未使用的字典:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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();