using pattern

Mon, July 3, 2006, 04:20 PM under dotNET
Previously we described the using statement. After showing a quick code example and describing the intent of the construct, we proceeded to a more pragmatic description of what it does which I repeat here:
"The using statement accepts as an argument an object that implements IDisposable; it defines a coding block where the ctor of the said object is called at the start and the Dispose method is called in the end."

Taking the definition above, a design pattern is formed (or to be more precise in this case, an idiom):

Sometimes you have a piece of code that has to be enclosed between two code blocks A and B. Code blocks A and B are repeated in multiple places in your project(s). When you recognise that, you can extract a new class with a ctor containing code block A and the Dispose method containing code block B. Replace all client side occurrences with a using block passing in the newly extracted class.

As an example, instead of:
void SomeMethod()
{
Cursor.Current = Cursors.WaitCursor;
statusBar1.Text = "Busy...";
button1.Enabled = false;

// do some real work here

button1.Enabled = true;
statusBar1.Text = "Ready";
Cursor.Current = Cursors.Default;
}
we write:
void SomeMethod()
{
using (BusyTaskRegion bt = new BusyTaskRegion(statusBar1, button1))
{
// do some real work here
}
}
...after extracting the following class:
class BusyTaskRegion : IDisposable
{
private Control _c1;
private Control _c2;

public BusyTaskRegion(Control c1, Control c2)
{
this._c1 = c1;
this._c2 = c2;
Cursor.Current = Cursors.WaitCursor;
c1.Text = "Busy...";
c2.Enabled = false;
}

public void Dispose()
{
this._c1.Enabled = true;
this._c1.Text = "Ready";
Cursor.Current = Cursors.Default;
}
}
Another example would be measuring performance of some code (i.e. extract the timer setup and tear down into a class and then use it via using). I was trying to find the pattern formally documented online but I couldn't. However, I did find examples of its usage here, here and here (much better than my fictitious example above!).

When I first saw this (at a previous project for some impersonation code), it felt wrong on two levels. First, it felt like using was being misused in scenarios that it wasn't originally intended for (e.g. when people read the client side code they have to take an extra mental step to digest that no memory management stuff takes place). Second, it felt wrong to define classes that have just a constructor and a Dispose method with nothing else in-between.

What do you think?
Monday, November 3, 2008 5:02:00 PM (Pacific Standard Time, UTC-08:00)
Feels wrong to me too, although not unlike what someone might have done with c++ constructors and destructors.
Probably better to abstract but still have start end stop methods.
Anonymous
Comments are closed.