{"record":{"id":"9f198d6bd8763fa9","repo":"dotnet/wpf","slug":"sr-enumerator-collectionchanged-generaltransformcollection","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/GeneralTransformCollection.cs","lineNumber":797,"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":779,"sourceCodeEnd":815,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Generated/GeneralTransformCollection.cs#L779-L815","documentation":"Thrown by the collection enumerator's MoveNext when the underlying GeneralTransformCollection was modified after the enumerator was created. The enumerator's version stamp no longer matches the collection's, so iteration is aborted with an InvalidOperationException.","triggerScenarios":"Calling Add, Remove, Insert, Clear, or the indexer setter while a foreach loop is enumerating the collection — including modifications made from event handlers, animation callbacks, or another thread during enumeration.","commonSituations":"Enumerating a TransformCollection and adding transforms inside the loop, UI-driven handlers mutating the collection during enumeration, or cross-thread access without synchronization.","solutions":["Collect items to add/remove into a temporary list and apply them after the foreach completes","Iterate over a snapshot (e.g. collection.ToArray()) when mutation may occur","Use a for loop with index bounds checks if deliberate mutation-while-iterating is required"],"exampleFix":"// before\nforeach (var t in collection) { if (bad(t)) collection.Remove(t); }\n// after\nvar toRemove = collection.Where(bad).ToArray();\nforeach (var t in toRemove) { collection.Remove(t); }","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"bool done = false;\nwhile (!done) {\n  try { foreach (var t in collection.ToArray()) { Process(t); } done = true; }\n  catch (InvalidOperationException) { /* retry with fresh snapshot */ }\n}","preventionTips":["Never mutate a collection inside its own foreach loop","Iterate over a snapshot (ToArray) when mutation can occur","Synchronize cross-thread access or marshal mutations to the owning thread (Dispatcher)"],"tags":["wpf","invalidoperationexception","enumerator","collection-modified"],"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"}