{"record":{"id":"71c556fff4416509","repo":"dotnet/wpf","slug":"sr-enumeratorinvalidoperation","errorCode":null,"errorMessage":"SR.EnumeratorInvalidOperation","messagePattern":"SR\\.EnumeratorInvalidOperation","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/Controls/ModelTreeEnumerator.cs","lineNumber":77,"sourceCode":"                _index = value;\n            }\n        }\n\n        protected virtual object Current\n        {\n            get\n            {\n                // Don't VerifyUnchanged(); According to MSDN:\n                //     If the collection is modified between MoveNext and Current,\n                //     Current will return the element that it is set to, even if\n                //     the enumerator is already invalidated.\n\n                if (_index == 0)\n                {\n                    return _content;\n                }\n                // Exception is part of the IEnumerator.Current contract when moving beyond begin/end\n                throw new InvalidOperationException(SR.EnumeratorInvalidOperation);\n            }\n        }\n\n        protected virtual bool MoveNext()\n        {\n            if (_index < 1)\n            {\n                // Singular content, can move next to 0 and that's it.\n                _index++;\n\n                if (_index == 0)\n                {\n                    // don't call VerifyUnchanged if we're returning false anyway.\n                    // This permits users to change the Content after enumerating\n                    // the content (e.g. in the invalidation callback of an inherited\n                    // property).  See bug 955389.\n\n                    VerifyUnchanged();","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/Controls/ModelTreeEnumerator.cs#L59-L95","documentation":"ModelTreeEnumerator's IEnumerator.Current getter throws InvalidOperationException('EnumeratorInvalidOperation') when Current is accessed before MoveNext() has positioned the enumerator at the first element. This is part of the documented IEnumerator.Current contract: Current is invalid before begin and after end.","triggerScenarios":"Accessing the enumerator's Current property immediately after GetEnumerator() without calling MoveNext() first, or after MoveNext() returned false and Reset() was not called.","commonSituations":"Hand-written foreach replacements, enumerator passed to code that reads Current optimistically, custom LINQ-like helpers that peek at Current, or iterating model content (ItemsControl items / UIElementCollection wrappers) with a stale enumerator after the collection was emptied.","solutions":["Call MoveNext() (and check it returned true) before reading Current.","Reset() the enumerator (or get a fresh one via GetEnumerator()) after it is exhausted.","Replace manual enumeration with foreach or LINQ, which honor the contract.","Check that content was not cleared, which can leave an enumerator positioned beyond end."],"exampleFix":"// before\nvar e = items.GetEnumerator();\nvar first = e.Current; // throws\n// after\nvar e = items.GetEnumerator();\nif (e.MoveNext()) { var first = e.Current; }","handlingStrategy":"try-catch","validationCode":"bool canReadCurrent = enumerator.MoveNext(); // check returned true before reading Current","typeGuard":null,"tryCatchPattern":"try { var current = enumerator.Current; }\ncatch (InvalidOperationException) { /* call MoveNext/Reset first */ }","preventionTips":["Always gate Current reads on MoveNext() returning true.","Use foreach or LINQ instead of manual enumerator management.","Reset or re-acquire the enumerator after exhaustion.","Never cache enumerator Current values between iterations."],"tags":["wpf","enumerator","ienumerable"],"backgroundTag":"unsupported-operation","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-21T21:30:21.729Z"}