{"record":{"id":"8c900f4befabf9f8","repo":"dotnet/wpf","slug":"sr-enumerator-reachedend-point3dcollection","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/Media3D/Generated/Point3DCollection.cs","lineNumber":873,"sourceCode":"            /// off the end of the list. However, the IEnumerable.Current\n            /// contract requires that we throw exceptions\n            /// </summary>\n            public Point3D 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 Point3D _current;\n            private Point3DCollection _list;\n            private uint _version;\n            private int _index;\n            #endregion\n        }\n        #endregion\n\n        #region Constructors\n\n        //------------------------------------------------------","sourceCodeStart":855,"sourceCodeEnd":891,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media3D/Generated/Point3DCollection.cs#L855-L891","documentation":"Point3DCollection's enumerator Current property throws InvalidOperationException(SR.Enumerator_ReachedEnd) when Current is accessed after enumeration completed (MoveNext returned false, _index == -2). Same fail-fast contract as the BCL List<T> enumerator.","triggerScenarios":"Accessing e.Current after a foreach or while(MoveNext()) loop finished; reading Current of an exhausted enumerator without Reset().","commonSituations":"Grabbing 'the last visited item' after loop exit; debugging code that reads Current post-enumeration.","solutions":["Capture the current item in a local variable inside the loop instead of reading Current afterwards","Call Reset() (on an unmodified collection) before re-reading, or get a fresh enumerator","Restructure to use foreach with a variable holding the element of interest"],"exampleFix":"// before\nPoint3D last;\nforeach (Point3D p in collection) { }\nlast = ((Point3DCollection.Enumerator)en).Current; // throws\n// after\nPoint3D last = default;\nforeach (Point3D p in collection) { last = p; }","handlingStrategy":"type-guard","validationCode":"bool canRead = lastMoveNextReturnedTrue; // track MoveNext outcome in a variable","typeGuard":"bool TryGetCurrent(Point3DCollection.Enumerator e, ref bool finished, out Point3D cur) { cur = default; if (finished) return false; cur = e.Current; return true; }","tryCatchPattern":"try { var cur = e.Current; }\ncatch (InvalidOperationException) { /* enumerator exhausted; capture items inside the loop instead */ }","preventionTips":["Store the desired item in a local inside the loop, not via Current afterwards","Use foreach so Current is never read post-loop","Reset or re-create the enumerator before another pass"],"tags":["wpf","enumeration","invalidoperation"],"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"}