词典方法“删除并清除”(.NET Core)中的异常行为

The*_*ias 5 c# dictionary .net-core

我正在尝试实现一种用于安全地枚举集合的缓存机制,并且正在检查内置集合的所有修改是否触发了InvalidOperationException由其各自的枚举器抛出的异常。我注意到,在.NET Core平台中,Dictionary.RemoveDictionary.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}");
Run Code Online (Sandbox Code Playgroud)

输出:

[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}");
Run Code Online (Sandbox Code Playgroud)

输出:

[1,您好]
计数:0

预期的例外是:

InvalidOperationException:集合已被修改;枚举操作可能无法执行。

...由方法Add以及.NET Framework中的相同方法抛出。

.NET Core 3.0.0,C#8,VS 2019 16.3.1,Windows 10

dbc*_*dbc 5

这似乎是.Net完整框架和.Net core for之间的故意区别Dictionary<TKey, TValue>

差异发生在Pull#18854中:从Dictionary中删除版本增量。删除重载

从删除操作中删除版本增量

这解决了api更改Add Dictionary.Remove(predicate)的coreclr方面,旨在允许从字典中删除项目,同时从@jkotas枚举每个方向。相关的corefx PR中包含所有集合测试和修改的测试,以及新添加的测试。

似乎存在公开的文档问题:

问题#42123:阐明枚举过程中字典行为/突变周围的保证

可以说当前Dictionary的实现在迭代过程中支持非并发突变是否正确?

只能移除。这已作为dotnet / coreclr#18854中的功能启用。

这可以依靠未来吗

是。

我们应该确保对文档进行更新以反映这一点。

您可能想对公开文档问题进行投票,要求澄清,因为.Net core 3.0文档Dictionary<TKey,TValue>.GetEnumerator()现在已过时

如果对集合进行了更改(例如添加,修改或删除元素),则枚举数将无法恢复,并且下一次调用MoveNextIEnumerator.Reset引发InvalidOperationException

奇怪的是,在枚举期间修改字典时,确实会抛出for的枚举器。SortedDictionary<TKey, TValue>

演示:

  • 错误报告在这里:https://github.com/dotnet/corefx/issues/42212 (2认同)