Страницы

Поиск по вопросам

четверг, 11 октября 2018 г.

Каким образом foreach узнаёт, что коллекция была изменена?

Как известно, если во время работы foreach коллекция, которую он перебирает будет изменена (в другом потоке, например), то произойдёт исключение. Но как устроен этот механизм исключений? Кто ответственен за обнаружение изменения? Должен ли я при разработке своих коллекций принимать какие-то меры для поддержки этого поведения или всё всегда будет заводиться из коробки?


Ответ

Цикл foreach эквивалентен приблизительно следующему коду:
int[] a = { 1, 2, 3, 4 }; var enumerator = ((IEnumerable)a).GetEnumerator(); while (enumerator.MoveNext()) { var item = enumerator.Current; // ... тело цикла ... }
Таким образом, все зависит от реализации метода IEnumerable.GetEnumerator() в конкретной коллекции. Для большинства встроенных в .Net коллекций этот метод возвращает класс, который и следит за приватным свойством version коллекций. Которое, в свою очередь увеличивается на 1 каждый раз, когда коллекция меняется.
За исключением одного бага, о котором я уже писал в майкрософт, но толку это не поимело. Метод List.Sort(Comparison comparison) не вызывает инкремент версии.

Комментариев нет:

Отправить комментарий