字典方法 Remove 和 Clear (.NET Core) 在枚举期间修改集合。没有抛出异常
Dictionary methods Remove and Clear (.NET Core) modify the collection during enumeration. No exception thrown
我正在尝试为 enumerating collections safely, and I am checking if all modifications of the built-in collections are triggering an InvalidOperationException
to be thrown by their respective enumerators. I noticed that in the .NET Core platform the Dictionary.Remove
and 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] removed: True
[2, World] removed: True
Count: 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]
Count: 0
预期的异常是:
InvalidOperationException: Collection was modified; enumeration operation may not execute.
...由方法 Add
和 .NET Framework 中的相同方法抛出。
.NET 核心 3.0.0、C# 8、VS 2019 16.3.1、Windows 10
对于 Dictionary<TKey, TValue>
,这似乎是 .Net 完整框架和 .Net 核心之间的故意差异。
分歧发生在Pull #18854: Remove version increment from Dictionary.Remove overloads:
Removes the version increment from Remove operations
This addresses the coreclr side of the api change Add Dictionary.Remove(predicate) with the intention of allowing removal of items from the dictionary while enumerating per direction from @jkotas . All collections tests and modified and new tests added in the related corefx PR.
似乎有一个未解决的文档问题:
Issue #42123: Clarify Dictionary behavior/guarantees around mutation during enumeration:
Is it correct to say that the current implementation of Dictionary supports non-concurrent mutation during iteration?
仅删除。这是在 dotnet/coreclr#18854.
中作为一项功能启用的
is this something that can be depended on going forward
是的。
我们应该确保更新文档以反映这一点。
您可能想对打开的文档问题添加投票以请求澄清,因为 .Net core 3.0 documentation for Dictionary<TKey,TValue>.GetEnumerator()
现在 已过时:
If changes are made to the collection, such as adding, modifying, or deleting elements, the enumerator is irrecoverably invalidated and the next call to MoveNext
or IEnumerator.Reset
throws an InvalidOperationException
.
奇怪的是,SortedDictionary<TKey, TValue>
的枚举器 在枚举期间修改字典时会抛出。
演示:
- .Net 框架
Remove()
:https://dotnetfiddle.net/8vONOw(抛出)。
- .Net core
Remove()
: https://dotnetfiddle.net/es6STm(不抛).
- .Net core
Add()
: https://dotnetfiddle.net/6q7Lvx (throws).
- .Net core
Remove()
from SortedDictionary<int, string>
: https://dotnetfiddle.net/bssrG7 (throws).
澄清更改何时可用以及通过哪些方法...
Microsoft 关于字典 .Remove and .Clear 的文档已更新:
.NET Core 3.0+ only: this mutating method may be safely called without invalidating active enumerators on the Dictionary<TKey,TValue> instance. This does not imply thread safety.
.NET Core 3.0 附带 C# 8.0。从那时起,我们只能通过 .Remove and .Clear 在枚举 (foreach
) 期间修改 Dictionary。
我正在尝试为 enumerating collections safely, and I am checking if all modifications of the built-in collections are triggering an InvalidOperationException
to be thrown by their respective enumerators. I noticed that in the .NET Core platform the Dictionary.Remove
and 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] removed: True
[2, World] removed: True
Count: 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]
Count: 0
预期的异常是:
InvalidOperationException: Collection was modified; enumeration operation may not execute.
...由方法 Add
和 .NET Framework 中的相同方法抛出。
.NET 核心 3.0.0、C# 8、VS 2019 16.3.1、Windows 10
对于 Dictionary<TKey, TValue>
,这似乎是 .Net 完整框架和 .Net 核心之间的故意差异。
分歧发生在Pull #18854: Remove version increment from Dictionary.Remove overloads:
Removes the version increment from Remove operations
This addresses the coreclr side of the api change Add Dictionary.Remove(predicate) with the intention of allowing removal of items from the dictionary while enumerating per direction from @jkotas . All collections tests and modified and new tests added in the related corefx PR.
似乎有一个未解决的文档问题:
Issue #42123: Clarify Dictionary behavior/guarantees around mutation during enumeration:
Is it correct to say that the current implementation of Dictionary supports non-concurrent mutation during iteration?
仅删除。这是在 dotnet/coreclr#18854.
中作为一项功能启用的is this something that can be depended on going forward
是的。
我们应该确保更新文档以反映这一点。
您可能想对打开的文档问题添加投票以请求澄清,因为 .Net core 3.0 documentation for Dictionary<TKey,TValue>.GetEnumerator()
现在 已过时:
If changes are made to the collection, such as adding, modifying, or deleting elements, the enumerator is irrecoverably invalidated and the next call to
MoveNext
orIEnumerator.Reset
throws anInvalidOperationException
.
奇怪的是,SortedDictionary<TKey, TValue>
的枚举器 在枚举期间修改字典时会抛出。
演示:
- .Net 框架
Remove()
:https://dotnetfiddle.net/8vONOw(抛出)。 - .Net core
Remove()
: https://dotnetfiddle.net/es6STm(不抛). - .Net core
Add()
: https://dotnetfiddle.net/6q7Lvx (throws). - .Net core
Remove()
fromSortedDictionary<int, string>
: https://dotnetfiddle.net/bssrG7 (throws).
澄清更改何时可用以及通过哪些方法...
Microsoft 关于字典 .Remove and .Clear 的文档已更新:
.NET Core 3.0+ only: this mutating method may be safely called without invalidating active enumerators on the Dictionary<TKey,TValue> instance. This does not imply thread safety.
.NET Core 3.0 附带 C# 8.0。从那时起,我们只能通过 .Remove and .Clear 在枚举 (foreach
) 期间修改 Dictionary