Search code examples
c#design-patternsidisposable

Looking for a design pattern similar to IDisposable (and Using)


I have a class that has a Start and an End method. I want to ensure that whenever a begin is called that the end must be called. For example:

var foo = new foo;
foo.Start();
...do other stuff
foo.End();

But I want to ensure that another developer cant call foo.Start without calling foo.End.

This would accomplish that but it requires the other developers to know to do it.

try
{
    foo.Start();
...do other stuff
}
finally
{
    foo.End();
}

I would love it to be similar to using where the dispose (or the end in this case) automatically call end when out of scope

using (foo.Start())
{
    //...do other stuff
}

Any Ideas or suggestions?

I've tried various patterns but can't get something I like and believe there must be something better.


Solution

  • Thank you everyone.. with your input I came up with this (consider this pseudo code, IDisposable is not complete, names are for the example not correct, etc..its paired down to the min)

    public class MyStack
    {
        public IDisposable Transaction()
        {
            return new UndoStackTransaction(this);
        }
    
        public void BeginCommit()
        {
        }
    
        public void EndCommit()
        {
        }
    
        public class UndoStackTransaction : IDisposable
        {
            private MyStack _myStack;
    
            public UndoStackTransaction(MyStack undoStack)
            {
                _myStack = undoStack;
                _myStack.BeginCommit();
            }
    
            ~UndoStackTransaction() => Dispose(false);
    
            public void Dispose()
            {
                Dispose(true);
                GC.SuppressFinalize(this);
            }
    
            protected virtual void Dispose(bool disposing)
            {
                _myStack.EndCommit();
            }
        }
    }
    

    Which allows me to do this....

       using (var transaction = stack.Transaction())
       {
           //Do Something
       }