{"record":{"id":"08198772d8b528f2","repo":"dotnet/wpf","slug":"sr-enumerator-reachedend-model3dcollection","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/Model3DCollection.cs","lineNumber":887,"sourceCode":"            /// off the end of the list. However, the IEnumerable.Current\n            /// contract requires that we throw exceptions\n            /// </summary>\n            public Model3D 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 Model3D _current;\n            private Model3DCollection _list;\n            private uint _version;\n            private int _index;\n            #endregion\n        }\n        #endregion\n\n        #region Constructors\n\n        //------------------------------------------------------","sourceCodeStart":869,"sourceCodeEnd":905,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media3D/Generated/Model3DCollection.cs#L869-L905","documentation":"Model3DCollection's enumerator Current property throws InvalidOperationException(SR.Enumerator_ReachedEnd) when Current is accessed after MoveNext has returned false (i.e. the enumerator position is past the end, _index == -2). The WPF generated collection enumerators enforce strict access ordering: Current is only valid while positioned on an element.","triggerScenarios":"Accessing the Current property after a foreach loop has completed, or after calling MoveNext() until it returns false and then reading Current without calling Reset().","commonSituations":"Reusing a single enumerator object across multiple passes; storing the enumerator and reading Current after loop exit; hand-rolled iterator loops that forget to Reset() before reuse.","solutions":["Read Current only inside the loop, immediately after MoveNext() returns true","Call Reset() before reusing an enumerator, or simply create a new one via GetEnumerator()","Prefer a foreach loop over manual MoveNext/Current code so the compiler enforces correct usage"],"exampleFix":"// before\nvar e = collection.GetEnumerator();\nwhile (e.MoveNext()) { }\nConsole.WriteLine(e.Current); // throws\n// after\nforeach (Model3D m in collection)\n    Console.WriteLine(m);","handlingStrategy":"try-catch","validationCode":"bool canReadCurrent = enumeratorHasStarted && !enumeratorFinished; // track MoveNext results yourself","typeGuard":"bool CanReadCurrent(System.Collections.IEnumerator e, bool lastMoveNextResult) => lastMoveNextResult;","tryCatchPattern":"try { var cur = e.Current; }\ncatch (InvalidOperationException) { /* enumerator past end; re-enumerate */ e.Reset(); }","preventionTips":["Use foreach instead of manual MoveNext/Current loops","Never read Current outside an active loop iteration","Create a fresh enumerator for each pass instead of reusing"],"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-21T21:30:21.729Z"}