Если вы используете словарь вместо хеш-таблицы, чтобы был известен тип ключей, самый простой способ сделать копию коллекции ключей, чтобы избежать этого исключения:
foreach (string key in new List<string>(dictionary.Keys))
Почему вы получаете исключение, говорящее вам, что вы изменили коллекцию, которую перебираете, хотя на самом деле это не так?
Внутри класса Hashtable есть поле версии. Методы Add, Insert и Remove увеличивают эту версию. Когда вы создаете перечислитель в любой из коллекций, предоставляемых Hashtable, объект перечислителя включает текущую версию Hashtable. Метод MoveNext перечислителя сравнивает версию перечислителя с версией Hashtable и, если они не равны, выдает InvalidOperationException, которое вы видите.
Это очень простой механизм для определения того, была ли изменена хеш-таблица. На самом деле это слишком просто. Коллекция Keys действительно должна поддерживать свою собственную версию, а ее метод GetEnumerator должен сохранять версию коллекции в перечислителе, а не версию Hashtable.
В этом подходе есть еще один, более тонкий конструктивный дефект. Версия представляет собой Int32. Метод UpdateVersion не проверяет границы. Поэтому возможно, если вы сделаете точно нужное количество модификаций в хеш-таблице (2 раза Int32.MaxValue
, плюс-минус), чтобы версия в хеш-таблице и в перечислителе были одинаковыми, даже если вы радикально изменили хэш-таблицу с момента создания. счетчик. Таким образом, метод MoveNext не будет генерировать исключение, хотя и должен, и вы получите неожиданные результаты.
person
Robert Rossney
schedule
29.11.2008