{"record":{"id":"002fa33d2b6aaeef","repo":"dotnet/wpf","slug":"sr-enumerator-collectionchanged-point3dcollection","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/Point3DCollection.cs","lineNumber":816,"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":798,"sourceCodeEnd":834,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media3D/Generated/Point3DCollection.cs#L798-L834","documentation":"Point3DCollection's enumerator MoveNext throws InvalidOperationException(SR.Enumerator_CollectionChanged) when the collection's version changed since the enumerator was created. The enumerator compares its cached _version against the list's _version and invalidates itself to guarantee fail-fast enumeration.","triggerScenarios":"Calling MoveNext() on an enumerator after any Add/Remove/Clear (or other version-bumping mutation) on the owning Point3DCollection between GetEnumerator() and MoveNext.","commonSituations":"Modifying the collection inside a foreach loop; another thread/UI handler mutating the collection during enumeration; enumerating while a deferred animation or data binding updates the list.","solutions":["Do not modify the collection while enumerating; enumerate a snapshot copy (ToList) if you must mutate","Collect items to remove into a separate list and apply changes after the loop","Use a for loop over indices with care, or lock if cross-thread access is possible"],"exampleFix":"// before\nforeach (Point3D p in collection)\n    if (p.X == 0) collection.Remove(p); // throws on next MoveNext\n// after\nforeach (Point3D p in collection.ToList())\n    if (p.X == 0) collection.Remove(p);","handlingStrategy":"try-catch","validationCode":"// no pre-call check possible; version is internal. Snapshot instead:\nvar snapshot = collection.ToList(); // enumerate snapshot if mutation is expected","typeGuard":null,"tryCatchPattern":"try { foreach (var p in collection) { /* ... */ } }\ncatch (InvalidOperationException) { /* collection changed during enumeration; retry with snapshot */ foreach (var p in collection.ToList()) { } }","preventionTips":["Never mutate a Point3DCollection during foreach","Collect mutations in a pending list and apply after the loop","Snapshot with ToList() when another thread or binding may mutate","Re-enumerate after any modification instead of reusing enumerators"],"tags":["wpf","enumeration","collection-modified"],"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"}