{"record":{"id":"e7dffd074ed5e120","repo":"dotnet/wpf","slug":"sr-enumerator-reachedend-doublecollection","errorCode":null,"errorMessage":"SR.Enumerator_ReachedEnd","messagePattern":"SR\\.Enumerator_ReachedEnd","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Generated/DoubleCollection.cs","lineNumber":872,"sourceCode":"            /// off the end of the list. However, the IEnumerable.Current\n            /// contract requires that we throw exceptions\n            /// </summary>\n            public double Current\n            {\n                get\n                {\n                    if (_index > -1)\n                    {\n                        return _current;\n                    }\n                    else if (_index == -1)\n                    {\n                        throw new InvalidOperationException(SR.Enumerator_NotStarted);\n                    }\n                    else\n                    {\n                        Debug.Assert(_index == -2, \"expected -2, got \" + _index + \"\\n\");\n                        throw new InvalidOperationException(SR.Enumerator_ReachedEnd);\n                    }\n                }\n            }\n\n            #endregion\n\n            #region Data\n            private double _current;\n            private DoubleCollection _list;\n            private uint _version;\n            private int _index;\n            #endregion\n        }\n        #endregion\n\n        #region Constructors\n\n        //------------------------------------------------------","sourceCodeStart":854,"sourceCodeEnd":890,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Generated/DoubleCollection.cs#L854-L890","documentation":"The DoubleCollection enumerator's Current throws InvalidOperationException with SR.Enumerator_ReachedEnd when enumeration has completed (_index == -2, i.e. MoveNext returned false) and Current is accessed again. There is no current element once the enumerator is past the last item.","triggerScenarios":"Iterating with MoveNext() until it returns false, then reading Current again; re-reading Current after a loop terminates; holding the enumerator after foreach completes and touching Current.","commonSituations":"Loop code that unconditionally reads Current after the while loop exits; caching the last-visited element via Current after iteration instead of storing it inside the loop.","solutions":["Read Current only inside the loop body while MoveNext() returns true.","Store the needed element in a local variable during iteration for use afterwards.","Create a new enumerator if you need to iterate again from the start."],"exampleFix":"// before\nwhile (e.MoveNext()) {}\nvar last = e.Current; // InvalidOperationException: Enumerator_ReachedEnd\n// after\ndouble last = double.NaN;\nwhile (e.MoveNext()) { last = e.Current; }","handlingStrategy":"type-guard","validationCode":"// only read Current when the last MoveNext() returned true\nbool hasCurrent = e.MoveNext();\nif (hasCurrent) { var d = e.Current; }","typeGuard":null,"tryCatchPattern":"try { var d = e.Current; }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"Enumerator_ReachedEnd\"))\n{ /* enumerator exhausted; recreate or use value saved in-loop */ }","preventionTips":["Read Current only inside while (MoveNext()) bodies.","Save needed elements to locals inside the loop, not after it.","Do not reuse an exhausted enumerator; create a new one for a second pass."],"tags":["wpf","enumerator","current","invalid-state"],"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"}