c# - 字典方法 Remove 和 Clear (.NET Core) 在枚举期间修改集合。没有抛出异常
问题描述
我正在尝试实现一种缓存机制来安全地枚举集合,并且我正在检查内置集合的所有修改是否都触发了InvalidOperationException
它们各自的枚举器抛出的问题。我注意到在 .NET Core 平台中,Dictionary.Remove
andDictionary.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,你好]
计数:0
预期的例外是:
InvalidOperationException:集合已修改;枚举操作可能无法执行。
...由 method 引发Add
,并由 .NET Framework 中的相同方法引发。
.NET Core 3.0.0、C# 8、VS 2019 16.3.1、Windows 10
解决方案
这似乎是 .Net 完整框架和 .Net 核心之间的故意区别Dictionary<TKey, TValue>
。
分歧发生在Pull #18854: Remove version increment from Dictionary.Remove 重载:
从 Remove 操作中删除版本增量
这解决了 api 更改Add Dictionary.Remove(predicate)的 coreclr 方面,目的是允许从字典中删除项目,同时从 @jkotas 枚举每个方向。在相关的 corefx PR 中添加了所有集合测试以及修改和新的测试。
似乎有一个开放的文档问题:
说字典的当前实现在迭代期间支持非并发突变是否正确?
只有拆除。这是dotnet/coreclr#18854中的一项功能。
这是可以依靠的东西吗?
是的。
我们应该确保更新文档以反映这一点。
您可能想要对请求澄清的开放文档问题添加投票,因为.Net core 3.0 文档Dictionary<TKey,TValue>.GetEnumerator()
现已过时:
如果对集合进行了更改,例如添加、修改或删除元素,则枚举器将不可恢复地失效,并且下一次调用
MoveNext
或IEnumerator.Reset
抛出InvalidOperationException
.
奇怪的是,在枚举期间修改字典时,枚举器确实会抛出。SortedDictionary<TKey, TValue>
演示:
推荐阅读
- c++ - 将字符串传递给模板函数
- sql - MS Access 将文本字段绑定到表格
- c# - 跨多个 DbContexts 与队列消息的 EF Core 事务
- tfs - VSTS:查询以在估计工作量的 75% 内完成工作项
- computer-science - 什么是应用于计算机编程和编程语言的上下文管理器?
- php - PDO $statement -> 可以执行多个参数吗?
- javascript - moment.js 没有创建正确的日期
- javascript - 如何使用动态导入导入单个组件?
- macos - Python 虚拟环境,Py2app 构建,wxpython 错误
- c# - 某些要插入的对象重复时的 Web API 响应