{"record":{"id":"106a957a30540c70","repo":"dotnet/wpf","slug":"sr-enumerator-collectionchanged-drawingcollection","errorCode":null,"errorMessage":"SR.Enumerator_CollectionChanged","messagePattern":"SR\\.Enumerator_CollectionChanged","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Generated/DrawingCollection.cs","lineNumber":832,"sourceCode":"            {\n                _list.ReadPreamble();\n\n                if (_version == _list._version)\n                {\n                    if (_index > -2 && _index < _list._collection.Count - 1)\n                    {\n                        _current = _list._collection[++_index];\n                        return true;\n                    }\n                    else\n                    {\n                        _index = -2; // -2 indicates \"past the end\"\n                        return false;\n                    }\n                }\n                else\n                {\n                    throw new InvalidOperationException(SR.Enumerator_CollectionChanged);\n                }\n            }\n\n            /// <summary>\n            /// Sets the enumerator to its initial position, which is before the\n            /// first element in the collection.\n            /// </summary>\n            public void Reset()\n            {\n                _list.ReadPreamble();\n\n                if (_version == _list._version)\n                {\n                    _index = -1;\n                }\n                else\n                {\n                    throw new InvalidOperationException(SR.Enumerator_CollectionChanged);","sourceCodeStart":814,"sourceCodeEnd":850,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Generated/DrawingCollection.cs#L814-L850","documentation":"DrawingCollection's Enumerator.MoveNext throws InvalidOperationException (SR.Enumerator_CollectionChanged) when the collection's version stamp changed since the enumerator was created. WPF collections use fail-fast enumeration: any Add/Insert/Remove invalidates outstanding enumerators instead of risking undefined behavior.","triggerScenarios":"Iterating a DrawingCollection with foreach while adding or removing items inside the loop body; modifying the collection from another thread or from an event handler fired during iteration.","commonSituations":"Removing a drawing when a condition is met mid-foreach; UI code that mutates a DrawingGroup's children inside a rendering/layout callback while a LINQ/foreach pass is in progress.","solutions":["Collect items to change into a separate list during iteration, then apply Add/Remove after the loop.","Use an index-based for loop iterating backwards when removing items.","Snapshot the collection first: foreach (var d in collection.ToArray()) so the enumerator operates on a copy."],"exampleFix":"// before\nforeach (var d in collection) { if (d is PenRemoved) collection.Remove(d); } // throws\n// after\nforeach (var d in collection.OfType<PenRemoved>().ToList()) collection.Remove(d);","handlingStrategy":"try-catch","validationCode":"var snapshot = collection.Cast<object>().ToArray(); // enumerate the snapshot, not the live collection","typeGuard":"null","tryCatchPattern":"try { foreach (var d in collection) { /* ... */ } } catch (InvalidOperationException ex) when (ex.Message.Contains(\"changed\")) { /* restart with a snapshot */ }","preventionTips":["Never Add/Remove inside foreach over a WPF Freezable collection","Batch mutations: collect changes, apply after the loop","Use ToArray()/ToList() snapshots for read passes","Marshal cross-thread mutations to the UI thread before enumerating"],"tags":["wpf","enumerator","collection-modified"],"backgroundTag":"collection-was-modified","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-22T01:17:13.364Z"}