Dictionary methods Remove and Clear (.NET Core) modify the collection during enumeration. No exception thrown

后端 未结 2 1961
心在旅途
心在旅途 2021-01-05 15:54

I am trying to implement a caching mechanism for enumerating collections safely, and I am checking if all modifications of the built-in collections are triggering an I

相关标签:
2条回答
  • 2021-01-05 16:31

    To clarify when the change was made available and via which methods...

    Microsoft's docs on the Dictionary's .Remove and .Clear have been updated:

    .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 came with C# 8.0. Since then, we have been able to modify a Dictionary<TKey,TValue> during enumeration (foreach) via .Remove and .Clear only.

    0 讨论(0)
  • 2021-01-05 16:44

    This appears to be an intentional difference between .Net full framework and .Net core for Dictionary<TKey, TValue>.

    The divergence occurred in 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.

    There appears to be an open documentation issue:

    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?

    Only removal. This was enabled as a feature in dotnet/coreclr#18854.

    is this something that can be depended on going forward

    Yes.

    We should ensure the docs are updated to reflect this.

    You might want to add a vote to the open doc issue requesting clarification as the .Net core 3.0 documentation for Dictionary<TKey,TValue>.GetEnumerator() is now obsolete:

    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.

    Strangely enough, the enumerator for SortedDictionary<TKey, TValue> does throw when the dictionary is modified during enumeration.

    Demos:

    • .Net framework Remove(): https://dotnetfiddle.net/8vONOw (throws).
    • .Net core Remove(): https://dotnetfiddle.net/es6STm (does not throw).
    • .Net core Add(): https://dotnetfiddle.net/6q7Lvx (throws).
    • .Net core Remove() from SortedDictionary<int, string>: https://dotnetfiddle.net/bssrG7 (throws).
    0 讨论(0)
提交回复
热议问题