Неожиданное поведение в методах словаря Remove and Clear (.NET Core) - PullRequest
5 голосов
/ 30 октября 2019

Я пытаюсь реализовать механизм кэширования для безопасного перечисления коллекций , и я проверяю, вызывают ли все модификации встроенных коллекций InvalidOperationException для соответствующих их перечислителей. Я заметил, что на платформе .NET Core методы Dictionary.Remove и Dictionary.Clear не вызывают это исключение. Это ошибка или функция?

Пример с Remove:

var dictionary = new Dictionary<int, string>();
dictionary.Add(1, "Hello");
dictionary.Add(2, "World");
foreach (var entry in dictionary)
{
    var removed = dictionary.Remove(entry.Key);
    Console.WriteLine($"{entry} removed: {removed}");
}
Console.WriteLine($"Count: {dictionary.Count}");

Вывод:

[1, Hello] удалено: True
[2, World] удалено: True
Количество: 0

Пример с Clear:

var dictionary = new Dictionary<int, string>();
dictionary.Add(1, "Hello");
dictionary.Add(2, "World");
foreach (var entry in dictionary)
{
    Console.WriteLine(entry);
    dictionary.Clear();
}
Console.WriteLine($"Count: {dictionary.Count}");

Вывод:

[1, Hello]
Количество: 0

Ожидаемое исключение:

InvalidOperationException: Коллекция была изменена;Операция перечисления может не выполняться.

... как создается методом Add и теми же методами в .NET Framework.

.NET Core 3.0.0, C # 8, VS 201916.3.1, Windows 10

Ответы [ 2 ]

5 голосов
/ 30 октября 2019

Кажется, что это преднамеренное различие между полной платформой .Net и ядром .Net для Dictionary<TKey, TValue>.

Расхождение произошло в Извлечение # 18854: удаление приращения версии из Dictionary.Remove overloads :

Удаляет приращение версии из операций удаления

Это относится к стороне coreclr изменения API Добавить Dictionary.Remove (предикат) с намерениемразрешить удаление элементов из словаря при перечислении по направлению от @jkotas. Все тесты наборов, а также измененные и новые тесты, добавленные в связанный PR corefx.

Похоже, что существует проблема с открытой документацией:

Проблема № 42123: Уточнение поведения словаря /гарантии вокруг мутации во время перечисления :

Правильно ли говорить, что текущая реализация словаря поддерживает неконкурентную мутацию во время итерации?

Onlyудаление. Это было включено как функция в dotnet / coreclr # 18854 .

- это то, что может зависеть от движения вперед

Да.

Мы должны убедиться, что документы обновлены, чтобы отразить это.

Возможно, вы захотите добавить голосование к вопросу открытого документа с просьбой дать разъяснения в виде документации .Net core 3.0 дляDictionary<TKey,TValue>.GetEnumerator() теперь устарел :

Если в коллекцию были внесены изменения, такие как добавление, изменение или удаление элементов,перечислитель безвозвратно аннулирован, и следующий вызов MoveNext или IEnumerator.Reset вызывает InvalidOperationException.

Как ни странно, перечислитель для SortedDictionary<TKey, TValue> делает throw при изменении словаря во время перечисления.

Демонстрации:

0 голосов
/ 30 октября 2019

Вы выполняли цикл для словаря, и в то же время вы очищали словарь, поэтому вы получали эту ошибку. Поскольку словарь используется, и вы изменили это. Если вы можете сделать это, удалив из цикла for, он будет работать нормально.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...