Search code examples
c#ienumerabledisposeyield-returnienumerator

Dispose vs. Iterator blocks


These two questions almost answer my own question, but not quite. Consider this a follow-up question to these.

I understand that a foreach loop will Dispose of an enumerator when it's done with it.

My question is this:

If the enumerator in question is actually a c# iterator block (i.e. GetEnumerator()/yield) of an IEnumerable<T> class which itself implements IDisposable, can I be sure that the object itself will be disposed? Or do I need to resort to calling GetEnumerator()/MoveNext()/Current explicitly inside a using block?

EDIT: This snippet demonstrates @JonSkeet's answer.

EDIT #2: This snippet, based on @JonSkeet's comments, demonstrates ideal usage. The iterator block is responsible for the lifetime of needed resources, not the enumerable object itself. This way, the enumerable can be enumerated multiple times if need be -- each enumerable has its own resource to work with.


Solution

  • If you want to dispose of the IEnumerable<T>, you need to do that yourself with a using statement (or manual try/finally). A foreach loop does not dispose of the IEnumerable<T> automatically - only the iterator it returns.

    So, you'd need:

    using (var enumerable = new MyEnumerable())
    {
        foreach (var element in enumerable)
        {
            ...
        }
    }
    

    It makes no difference whatsoever whether MyEnumerable implements IEnumerable<T> using an iterator block or some other code.