Начиная с .NET 5 Изменение Значений в Dictionary в Foreach не Выбрасывает Исключения
Давно известно, что внутри цикла
foreach нельзя изменять элементы коллекции. Однако, рассмотрим следующий код:var d = new Dictionary<string, int>
{ { "a", 0 }, { "b", 0 }, { "c", 0 } };
foreach (var k in d.Keys)
{
d[k]+=1;
}
В .NET Core 3.1 и ранее этот код выдавал ожидаемое исключение:System.InvalidOperationException: Collection was modified; enumeration operation may not execute. (Коллекция изменена; операция перечисления не может быть выполнена.)
Однако, начиная с .NET 5, он выполняется без проблем. Что случилось?
В исходный код
Dictionary<TKey, TValue> было внесено изменение, позволяющее обновлять значения по существующим ключам во время перечисления. Убрали обновление внутреннего поля _version при изменении элементов. Поле _version (которое используется для обнаружения изменений) теперь обновляется только при определённых условиях, но не при изменении значения по существующему ключу.Удаление из словаря с помощью метода Remove также больше не влияет на перечисление. Это, однако, существует с .NET Core 3.0 и соответствующим образом упоминается в документации метода
Remove:«Только .NET Core 3.0+: Этот метод изменения может быть безопасно вызван без аннуляции активных перечислителей экземпляра Dictionary<TKey,TValue>. Но это не подразумевает потокобезопасность.»
Несмотря на то, что вышеупомянутое изменение значений при перечислении просят внести в документацию, на момент выхода этого поста, этого пока не сделано.
Источник: https://stackoverflow.com/questions/66939923/what-changed-in-net-5-that-makes-it-not-throw-when-changing-dictionary-values-i