{"record":{"id":"f6c0cf146c040f94","repo":"dotnet/wpf","slug":"sr-enumerator-collectionchanged-transform3dcollection","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/Transform3DCollection.cs","lineNumber":830,"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":812,"sourceCodeEnd":848,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media3D/Generated/Transform3DCollection.cs#L812-L848","documentation":"The Transform3DCollection enumerator's MoveNext throws InvalidOperationException (SR.Enumerator_CollectionChanged) when the collection's version stamp no longer matches the version captured when the enumerator was created. WPF collections invalidate enumerators on any add/remove to prevent undefined iteration.","triggerScenarios":"Calling MoveNext after an element was added, removed, or replaced (indexer set) on the same collection during iteration.","commonSituations":"Removing items inside a foreach loop; a background thread mutating the collection while the UI thread iterates; building a filtered list by calling Remove while enumerating.","solutions":["Materialize the items first (foreach over collection.ToArray() or ToList()) before mutating.","Collect items to remove in a separate list, then remove them after the loop.","Synchronize access across threads (freeze the collection or dispatch mutations to one thread)."],"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":"try-catch","validationCode":"var snapshot = collection.ToArray();\nforeach (var t in snapshot) { /* safe to mutate collection */ }","typeGuard":null,"tryCatchPattern":"try { foreach (var t in collection) { /* ... */ } } catch (InvalidOperationException) { /* collection changed during iteration; restart with snapshot */ }","preventionTips":["Never Add/Remove inside foreach over the live collection","Iterate over ToArray()/ToList() when mutating","Keep all mutations of Freezable collections on a single (UI) thread","Freeze collections that should be immutable"],"tags":["wpf","collection","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"}