{"record":{"id":"8d4293fc9e2a52c7","repo":"dotnet/wpf","slug":"sr-enumerator-collectionchanged-pointcollection","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/PointCollection.cs","lineNumber":817,"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":799,"sourceCodeEnd":835,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Generated/PointCollection.cs#L799-L835","documentation":"The PointCollection enumerator is version-checked: it throws InvalidOperationException(Enumerator_CollectionChanged) from MoveNext when the collection's version counter no longer matches the version captured when the enumerator was created. WPF invalidates outstanding enumerators on any modification (Add, Remove, Clear, indexer set) so iteration never observes a collection mutated mid-enumeration.","triggerScenarios":"Calling MoveNext on an Enumerator after any structural change to the underlying PointCollection — e.g. points.Add(...) or points.RemoveAt(i) inside a foreach over points, or on another thread.","commonSituations":"Modifying a collection inside foreach and removing items; deferred logic that mutates the collection between obtaining the enumerator and iterating; UI/data updates on a different thread while an enumeration is in progress.","solutions":["Snapshot first: foreach over a copied array (points.ToArray()) and mutate the original.","Collect items to remove into a separate list, then apply the changes after the loop.","Use a for loop over the index (counting backwards for removals) instead of foreach.","Synchronize threads so no mutation happens while enumerating."],"exampleFix":"// before\nforeach (Point p in points)\n    if (p.X < 0) points.Remove(p); // InvalidOperationException\n// after\nforeach (Point p in points.ToArray())\n    if (p.X < 0) points.Remove(p);","handlingStrategy":"validation","validationCode":"long versionBefore = points.GetType().GetProperty(\"Version\", BindingFlags.NonPublic|BindingFlags.Instance)?.GetValue(points) as long? ?? 0; // or simply: iterate over a snapshot","typeGuard":"null","tryCatchPattern":"try { foreach (Point p in points) { /* ... */ } }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"CollectionChanged\")) { /* restart iteration over a fresh snapshot */ }","preventionTips":["Never Add/Remove/Clear a collection while enumerating it; enumerate points.ToArray() instead.","Collect mutations in a side list and apply them after the loop.","Avoid cross-thread mutation of UI-thread Freezable collections; use Dispatcher marshaling."],"tags":["wpf","enumerator","invalidoperationexception","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"}