{"record":{"id":"cca95ed38fc2e1a4","repo":"dotnet/wpf","slug":"sr-enumeratorversionchanged-columndefinition","errorCode":null,"errorMessage":"SR.EnumeratorVersionChanged","messagePattern":"SR\\.EnumeratorVersionChanged","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/ColumnDefinition.cs","lineNumber":924,"sourceCode":"            public void Dispose()\n            {\n                _currentElement = null;\n            }\n\n            /// <summary>\n            ///     Validates that\n            ///     enumerator is not disposed;\n            ///     enumerator is still in sync with collection;\n            /// </summary>\n            private void PrivateValidate()\n            {\n                if (_currentElement == null)\n                {\n                    throw new InvalidOperationException(SR.EnumeratorCollectionDisposed);\n                }\n                if (_version != _collection._version)\n                {\n                    throw new InvalidOperationException(SR.EnumeratorVersionChanged);\n                }\n            }\n\n            private ColumnDefinitionCollection _collection;              //  the collection to be enumerated\n            private int _index;                         //  current element index\n            private int _version;                       //  the snapshot of collection's version at the time of creation\n            private object _currentElement;             //  multipurpose:\n                                                        //  points to the collection object when enumerator is either before start or after end\n                                                        //  points to the current element while in the process of enumeration\n                                                        //  is null if disposed\n        }\n\n        #endregion Private Structures Classes\n    }\n\n    /// <summary>\n    ///     ColumnDefinition is a FrameworkContentElement used by Grid\n    ///     to hold column / row specific properties.","sourceCodeStart":906,"sourceCodeEnd":942,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/ColumnDefinition.cs#L906-L942","documentation":"ColumnDefinition.ColumnDefinitionCollection's enumerator detects that the collection's internal version counter no longer matches the version captured when the enumerator was created. WPF collections invalidate enumerators whenever the collection is modified, so continuing to enumerate after Add/Remove/Clear throws InvalidOperationException(SR.EnumeratorVersionChanged). This protects against undefined behavior from a mutated underlying list.","triggerScenarios":"Calling MoveNext() or Reset() on a ColumnDefinitionCollection enumerator after the collection was structurally modified (adding/removing ColumnDefinitions, Clear()) since the enumerator was obtained (e.g. modifying Grid.ColumnDefinitions inside a foreach over it).","commonSituations":"Dynamically adding columns to a Grid inside a foreach loop, a PropertyChanged/data-binding handler that mutates ColumnDefinitions while UI code is enumerating them, or sharing an enumerator across code that re-lays-out the grid.","solutions":["Snapshot the collection before mutating: iterate over a copy (e.g. columnDefinitions.Cast<ColumnDefinition>().ToArray()) so modifications don't invalidate the loop.","Restructure code so all Add/Remove/Insert calls on ColumnDefinitions happen outside the enumeration.","If you must mutate mid-loop, restart enumeration by fetching a fresh GetEnumerator() after each mutation.","Catch InvalidOperationException around MoveNext/Reset only when invalidation is expected and acceptable."],"exampleFix":"// before\nforeach (ColumnDefinition cd in grid.ColumnDefinitions)\n{\n    if (cd.Width.IsAuto) grid.ColumnDefinitions.Remove(cd); // throws\n}\n// after\nforeach (ColumnDefinition cd in grid.ColumnDefinitions.ToArray())\n{\n    if (cd.Width.IsAuto) grid.ColumnDefinitions.Remove(cd);\n}","handlingStrategy":"try-catch","validationCode":"var snapshot = grid.ColumnDefinitions.Cast<ColumnDefinition>().ToArray();\nbool canEnumerate = snapshot.Length == grid.ColumnDefinitions.Count;","typeGuard":"static bool IsEnumerationValid(ColumnDefinitionCollection c, int knownVersionCount) => c.Count == knownVersionCount;","tryCatchPattern":"try\n{\n    foreach (ColumnDefinition cd in grid.ColumnDefinitions) { /* ... */ }\n}\ncatch (InvalidOperationException)\n{\n    // collection changed mid-enumeration; restart with a snapshot\n}","preventionTips":["Never mutate ColumnDefinitions inside foreach over the same collection","Enumerate over ToArray() copies when mutation is possible","Defer collection changes to after the enumeration completes"],"tags":["wpf","enumerator","collection-modified","grid"],"backgroundTag":"internal-invariant-violation","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"}