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();