What changed in .net 5 that makes it not throw when changing dictionary values in foreach
31
In .NET<5 and .NET Core 3.1 the following code
var d = new Dictionary<string, int> { { "a", 0 }, { "b", 0 }, { "c", 0 } };
foreach (var k in d.Keys)
{
d[k]+=1;
}
throws
System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
When targeting .NET 5 the snippet no longer throws.
What has changed?
I failed to find the answer in Breaking changes in .NET 5 and Performance Improvements in .NET 5.
Is it something to do with ref readonly T?
c# .net-5
Dictionary<, >, starting reading from thesetaccessor of the indexerpublic TValue this[TKey key] { /* ... */ }. There should exist a private field that keeps track on whether the collection was modified or not. If I assign with the setterd[k] = tmp;andkwas previously in theDictionary<,>, does that count as a modification? They must have changed that. – Jeppe Stig Nielsen Apr 4 at 9:56entries[i].value = value; version++; return;in the branch where we have an update. Theversion++ensures the enumerator will blow up with an exception on the nextMoveNext()on the enumerator. – Jeppe Stig Nielsen Apr 4 at 10:02foreach (var v in d.Values) { Console.WriteLine("Top " + v + " " + d["c"]); d["c"] += 1; Console.WriteLine("Bottom " + v + " " + d["c"]); }. So I guess there is still only oneversionfield for both keys and values. Where do I see the new C# source ofpublic class Dictionary<TKey, TValue>?) – Jeppe Stig Nielsen Apr 4 at 10:23