Using the using-statement and pattern in C#

How often do find yourself writing code like this to do some things in batch:

BatchCalculatorcalc = newBatchCalculator();

calc.Suspend();

calc.CalculateSomething(something);

calc.CalculateSomethingElse(something);

calc.Resume();

Well, I do and I’m not really happy about sprinkling those Suspends and Resumes around everywhere I need to start and stop something. I see at least two common pitfalls with this solution and a minor hiccup:

Somewhere down the pipe I’m bound to forget the call to Resume explicitly and I’ll have a bug on my hands.

Somewhere in between the Suspend and Resume calls an Exception is thrown, Resume is never reached, and leaving the object in an unwanted state.

It could be better looking! ->

The short using-introduction

With the introduction of .NET and it’s managed environment and non-deterministic garbage collector, there were several figureheads in the industry that raised an eyebrow or two. There were also people raising more than their eyebrows as well, and according to legend and several .NET Rocks shows, Chris Sells (now a blue badge) was one. They allegedly made MS include an IDisposable interface with a simple method Dispose() to fill their garbage collection needs. And if that wasn’t enough, they included the using-statement which is a try-finally in disguise where the finally automatically calls IDisposable.Dispose()!

A couple of regulars in my world in that department are the IDbConnection interface and later (from 2.0 and onwards) the TransactionScope class, but it has also been recommended practice for any implementers of the IDisposable interface.

Yeah yeah, but what can I do with it?

With the aforementioned background in place we can exploit it to create a better and more fluent API for our batch-oriented processes. Let us simply dive into the code, and I introduce without further ado; the changed BatchCalculator:

publicclassBatchCalculator

{

publicIDisposableSuspend(){}

publicvoidResume(){}

publicvoidCalculateSomethingElse(objectsomething){}

publicvoidCalculateSomething(objectsomething){}

}

Suspend now returns an IDisposable and we can replace our calling code to this:

BatchCalculatorcalc = newBatchCalculator();

using(calc.Suspend())

{

calc.CalculateSomething(something);

calc.CalculateSomethingElse(something);

}

Yes! That’s more like it. I definitively like to looks of that.

But how.. do I ensure a call to Resume?

This is where the "magic" happens. Let us make a class which implements IDisposable that gets returned from our Suspend method:

publicclassSuspender : IDisposable

{

privatereadonlyBatchCalculatorm_calculator;

publicSuspender(BatchCalculatorcalculator)

{

m_calculator = calculator;

}

publicvoidDispose()

{

m_calculator.Resume();

}

}

And our revised Suspend method:

publicIDisposableSuspend()

{

returnnewSuspender(this);

}

Now go look at the implemented Dispose-method in our Suspender-class. It just calls our Resume method on our BatchCalculator! So when the using-block is exited, the Dispose-method is called and hooray, mission accomplished.

Finishing touch

To increase the applicability of the Suspender-class I introduce the role interface IResumable:

publicinterfaceIResumable

{

voidResume();

}

And implement it in BatchCalculculator:

publicclassBatchCalculator : IResumable

{

publicIDisposableSuspend()

{

returnnewSuspender(this);

}

publicvoidResume(){}

publicvoidCalculateSomethingElse(objectsomething){}

publicvoidCalculateSomething(objectsomething){}

}

Now the Suspender class can just wrap our new interface:

publicclassSuspender : IDisposable

{

privatereadonlyIResumablem_resumable;

publicSuspender(IResumableresumable)

{

m_resumable = resumable;

}

publicvoidDispose()

{

m_resumable.Resume();

}

}

Final note

If we revisit our weak spots, have we solved them all? A definitive yes; using using guarantees that the Dispose()-method is called which in turn calls our wrapped method. I must also add I really like the syntactic sugar using represents.

This pattern is obviously at a tangent for what using and IDisposable was supposed to be used for. The MSDN library has this to say about IDisposable:

The primary use of this interface is to release unmanaged resources.

But why not leverage what we have available. After all, coding is done once. Reading it is another matter completely.