Коллекция модифицируется во время цикла, когда это никак не может быть С#

Оператор foreach в следующем коде создает исключение InvalidOperationException, говорящее: «Коллекция была изменена. Операция перечисления не может быть выполнена». Я не понимаю, как это возможно, поскольку цвета никогда не могут быть изменены после инициализации.

Dictionary<Color, int> colorDictionary = new Dictionary<Color, int>();
//Put stuff in colorDictionary...
int currentBest = 257;
Color replaceColor = Color.Empty;
Dictionary<Color, int>.KeyCollection colors = colorDictionary.Keys;
foreach (Color c in colors)
{
    if (colorDictionary[c] == 0)
    {
        continue;
    }
    if (ColorDistance(color, c) < currentBest)
    {
        replaceColor = c;
        colorDictionary[c]--;
    }
}

person AlphaModder    schedule 27.08.2014    source источник


Ответы (1)


Я не понимаю, как это возможно, поскольку цвета никогда не могут быть изменены после инициализации.

Это просмотр ключей словаря... и здесь вы изменяете словарь:

colorDictionary[c]--;

По общему признанию, на самом деле это не добавление или удаление каких-либо ключей, а изменение словаря, и перечислитель ключей в основном чувствителен к этому.

Самым простым решением было бы просто создать копию:

IEnumerable<Color> colors = colorDictionary.Keys.ToList();
person Jon Skeet    schedule 27.08.2014
comment
Насколько мне известно, в KeyCollection нет ToList(), поэтому я буду использовать CopyTo и сделать цвета Color[]. - person AlphaModder; 28.08.2014
comment
@ user1825860: Нет, но он реализует IEnumerable<TKey>, поэтому вы можете использовать метод расширения LINQ Enumerable.ToList(). Просто убедитесь, что у вас есть директива using для System.Linq. - person Jon Skeet; 28.08.2014
comment
О... упс. Я отредактировал свой комментарий с решением, пока вы ответили. Я воспользуюсь твоим, он лучше. - person AlphaModder; 28.08.2014