{"record":{"id":"cfabb2fc228268e8","repo":"dotnet/wpf","slug":"sr-enumerator-collectionchanged-doublecollection","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/DoubleCollection.cs","lineNumber":815,"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":797,"sourceCodeEnd":833,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Generated/DoubleCollection.cs#L797-L833","documentation":"The DoubleCollection enumerator's MoveNext validates that the collection's version stamp matches the version captured when enumeration began. If the collection was modified (Add/Remove/Insert/Clear) after the enumerator was created, it throws InvalidOperationException with SR.Enumerator_CollectionChanged. This protects callers from undefined iteration over a mutated list.","triggerScenarios":"Creating an enumerator (foreach over a DoubleCollection), then calling Add/Remove/Insert/Clear on the collection, then continuing MoveNext — the next MoveNext call after the change throws.","commonSituations":"Modifying a DoubleCollection inside a foreach loop over it (e.g. removing points while iterating animation keyframes); a callback or event handler mutating the collection during enumeration; multi-threaded updates without synchronization.","solutions":["Materialize the collection first (e.g. foreach over coll.ToArray() or ToList()) when you must modify during iteration.","Collect items to remove in a separate list, then apply removals after the loop ends.","Guard concurrent access with a lock so no mutation occurs while an enumerator is active."],"exampleFix":"// before\nforeach (double d in coll) { if (d < 0) coll.Remove(d); } // InvalidOperationException\n// after\nforeach (double d in coll.ToArray()) { if (d < 0) coll.Remove(d); }","handlingStrategy":"validation","validationCode":"// snapshot before iterating to survive mutations\nvar snapshot = coll.ToArray();","typeGuard":null,"tryCatchPattern":"try\n{\n    foreach (double d in snapshot) { /* mutate coll freely */ }\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"Enumerator_CollectionChanged\"))\n{ /* re-enumerate over a fresh snapshot */ }","preventionTips":["Never Add/Remove on a collection inside its own foreach.","Iterate over a ToArray()/ToList() snapshot when mutation is required.","Synchronize collection access across threads with a lock.","Batch modifications outside of enumeration loops."],"tags":["wpf","enumerator","collection-modified","foreach"],"backgroundTag":"collection-modified-during-enumeration","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"}