{"record":{"id":"2b15ed191d2b7a08","repo":"dotnet/wpf","slug":"sr-enumerator-collectionchanged-generaltransform3dcollection","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/Media3D/Generated/GeneralTransform3DCollection.cs","lineNumber":795,"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":777,"sourceCodeEnd":813,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media3D/Generated/GeneralTransform3DCollection.cs#L777-L813","documentation":"The GeneralTransform3DCollection enumerator is version-checked: MoveNext throws InvalidOperationException (Enumerator_CollectionChanged) if the collection's version differs from the version captured when enumeration started. Any add, remove, or structural change during iteration invalidates the enumerator.","triggerScenarios":"Calling Add/Insert/Remove/RemoveAt/Clear on the GeneralTransform3DCollection inside a foreach loop or between MoveNext calls.","commonSituations":"Removing transforms while iterating to 'clean up'; adding a transform inside an iteration based on a condition; collection mutated on another thread or via data binding during iteration.","solutions":["Iterate a snapshot: foreach (var t in collection.ToArray()) so mutations do not affect the loop.","Collect items to remove in a list, then apply removals after the loop.","Use a reverse for-loop over indices when removing by index."],"exampleFix":"// before\nforeach (var t in collection)\n    if (ShouldRemove(t)) collection.Remove(t);\n// after\nforeach (var t in collection.ToArray())\n    if (ShouldRemove(t)) collection.Remove(t);","handlingStrategy":"fallback","validationCode":"// snapshot before iterating\nvar snapshot = collection.ToArray();","typeGuard":null,"tryCatchPattern":"try\n{\n    foreach (var t in collection) { /* ... */ }\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"changed\"))\n{\n    foreach (var t in collection.ToArray()) { /* retry on snapshot */ }\n}","preventionTips":["Never mutate the collection inside foreach over it","Iterate collection.ToArray() when mutations are possible","Buffer removals and apply them after the loop","Marshal cross-thread mutations to the UI thread"],"tags":["wpf","invalid-operation-exception","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"}