char m
char m

Reputation: 8336

how to free resources in generic class implementing IEnumerable<T> when iteration is interrupted?

I have following class that wraps static methods of class MyDatabase and I need to close _cursor even if iteration is interrupted.

public class DbWrapper<T> : IEnumerable<T> where T : struct
{
    public static Dictionary<Type, int> _tablenumber = new Dictionary<Type, int>()
        {
           {  typeof(MyStruct), 100 }
           {  typeof(SomeStruct), 200 }
        };

    Cursor _cursor;

    public DbWrapper()
    {
        _cursor = MyDatabase.OpenCursorAll(_tablenumber[typeof(T)]);
    }

    IEnumerator<T> IEnumerable<T>.GetEnumerator()
    {
        T row;
        while (MyDatabase.Fetch<T>(_cursor, out row))
        {
            yield return row;
        }
        MyDatabase.CloseCursor(_cursor);
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        var me = this as IEnumerable<T>;
        return me.GetEnumerator();
    }
}

I could do this by making class implement IDisposable and creating DbWrapper instance in using block before the iteration. However I would like to minimize the calling code. I'm also wondering is it good style to call constructor directly in foreach:

        foreach (var eRow in new DbWrapper<MyStruct>())
        {
            myList.Add(eRow.Name);
        }

or should I have static method that returns the instance?

Upvotes: 0

Views: 57

Answers (1)

D Stanley
D Stanley

Reputation: 152616

I would like to minimize the calling code

If Cursor implements IDisposable you can just get rid of the creating of the cursor in the constructor and wrap the yield statement in a using block:

IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
    using(_cursor = MyDatabase.OpenCursorAll(_tablenumber[typeof(T)]))
    {
        T row;
        while (MyDatabase.Fetch<T>(_cursor, out row))
        {
            yield return row;
        }
        MyDatabase.CloseCursor(_cursor);
    }
}

Note that Dispose is automatically called when using a foreach even if the enumerator is not fully enumerated.

Upvotes: 1

Related Questions