{"record":{"id":"057ea43b73f4852b","repo":"dotnet/wpf","slug":"sr-enumerator-reachedend-collectionhelper","errorCode":null,"errorMessage":"SR.Enumerator_ReachedEnd","messagePattern":"SR\\.Enumerator_ReachedEnd","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/WpfGfx/codegen/mcg/helpers/CollectionHelper.cs","lineNumber":773,"sourceCode":"                        /// off the end of the list. However, the IEnumerable.Current\n                        /// contract requires that we throw exceptions\n                        /// </summary>\n                        public [[type]] 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 [[type]] _current;\n                        private [[resource.Name]] _list;\n                        private uint _version;\n                        private int _index;\n                        #endregion\n                    }\n                    #endregion\n                [[/inline]];\n        }\n\n        public static string WriteCollectionMethods(McgResource resource)","sourceCodeStart":755,"sourceCodeEnd":791,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/WpfGfx/codegen/mcg/helpers/CollectionHelper.cs#L755-L791","documentation":"This InvalidOperationException is thrown by a CollectionHelper-generated enumerator when Current is accessed after iteration has completed: MoveNext() returned false (internal _index == -2, meaning the enumerator is past the last element). It enforces the IEnumerator contract that Current is undefined once the enumeration is finished.","triggerScenarios":"Accessing Current after MoveNext() has returned false, or continuing to read Current after a foreach loop over the collection has finished.","commonSituations":"Keeping a reference to the enumerator and reading Current after the loop; trying to get the 'last' element after the loop ended instead of saving it inside the loop; reusing an exhausted enumerator.","solutions":["Capture the last value inside the loop before MoveNext() returns false.","Call Reset() (or obtain a fresh enumerator) to iterate again from the start.","Restructure as foreach so Current is only read at valid positions."],"exampleFix":"// before\nforeach (var x in collection) { }\nvar last = e.Current; // throws: reached end\n// after\nT last = default;\nforeach (var x in collection) { last = x; }","handlingStrategy":"try-catch","validationCode":"while (e.MoveNext())\n{\n    last = e.Current; // save inside the loop, never after\n}","typeGuard":"static bool TryLast<T>(IEnumerable<T> seq, out T value) { value = default; using var e = seq.GetEnumerator(); if (!e.MoveNext()) return false; value = e.Current; while (e.MoveNext()) value = e.Current; return true; }","tryCatchPattern":"try { var item = enumerator.Current; }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"ReachedEnd\") || ex.Message.Contains(\"end\")) { /* enumeration finished; re-enumerate if needed */ }","preventionTips":["Capture values inside the loop; do not read Current after it ends.","Get a fresh enumerator instead of reusing an exhausted one.","Use LINQ (Last(), First()) which manages enumerator state for you."],"tags":["enumerator","invalidoperation","wpf-codegen"],"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"}