{"record":{"id":"fefa4673da5d7ff0","repo":"dotnet/wpf","slug":"sr-enumerator-collectionchanged-collectionhelper","errorCode":null,"errorMessage":"SR.Enumerator_CollectionChanged","messagePattern":"SR\\.Enumerator_CollectionChanged","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/WpfGfx/codegen/mcg/helpers/CollectionHelper.cs","lineNumber":716,"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":698,"sourceCodeEnd":734,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/WpfGfx/codegen/mcg/helpers/CollectionHelper.cs#L698-L734","documentation":"This SR resource backs an InvalidOperationException thrown by the generated collection's enumerator (CollectionHelper.cs) when MoveNext detects the collection's version changed after the enumerator was created. The enumerator is invalidated to prevent skipping or duplicating elements.","triggerScenarios":"Calling MoveNext() on an enumerator obtained before any Add/Insert/Remove/Clear (or other version bump) on the same generated collection.","commonSituations":"Modifying a collection while enumerating it (e.g. removing items inside a foreach); enumerating on one thread while another mutates the collection; storing enumerators across update passes.","solutions":["Materialize the collection (ToList()) before mutating, or iterate over a snapshot","Collect pending changes and apply them after the loop","Avoid mutating the collection inside foreach; use a for loop over indices from the end when removing","Catch InvalidOperationException at the iteration boundary if concurrent mutation is possible and retry with a fresh enumerator"],"exampleFix":"// before\nforeach (var item in collection) if (pred(item)) collection.Remove(item); // throws\n// after\nforeach (var item in collection.ToList()) if (pred(item)) collection.Remove(item);","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { foreach (var i in collection) { /* no mutation */ } }\ncatch (InvalidOperationException) { iterateSnapshot(collection.ToList()); }","preventionTips":["Never mutate a collection inside foreach over it","Iterate a snapshot (ToList) when mutation is required","Avoid sharing enumerators across threads"],"tags":["wpf","enumerator","collection-modified","invalidoperation"],"backgroundTag":"invalid-state-transition","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"}