Usually this IEnumerator<> implements IDisposable , and if you look at the definition of IEnumerator<> , you will see that:
public interface IEnumerator<out T> : IDisposable, IEnumerator
The foreach correctly Dispose() IEnumerator<> , which gets from IEnumerable<> , so that:
IEnumerable<SomeClass> res = SomeQuery(); foreach (SomeClass sc in res) { if (something) break; }
when you exit foreach any way ( break , exception, naturally ending with res ), you should call Dispose() IEnumerator<> . See https://msdn.microsoft.com/en-us/library/aa664754(v=vs.71).aspx for an example implementation of foreach (a try ... finally ... with Dispose() inside finally )
Note that C # will generate the βcorrectβ code for using , used inside the yield function. See here: http://goo.gl/Igzmiz
public IEnumerable<Foo> Bar() { using (var r = OpenResource()) { while (r.Read ()) { yield return new Foo(); } } }
transforms into something that
void IDisposable.Dispose() { int num = this.<>1__state; if (num == -3 || num == 1) { try { } finally { this.<>m__Finally1(); } } }
The Dispose() method of IEnumerator<> will call the m__Finally1 method, which will be (IDisposable)this.<r>5__1.Dispose(); (where 5__1 is the r returned from OpenResource() ). m__Finally is called even if the code just βexitsβ from while (r.Read ()) :
if (!this.<r>5__1.Read()) { this.<>m__Finally1();
and / or if there is an exception.
catch { this.System.IDisposable.Dispose();