The purpose of the interface IDisposable
is to release unmanaged resources in an orderly fashion. It goes hand in hand with the using
keyword that defines a scope after the end of which the resource in question is disposed of.
Because this meachnism is so neat, I've been repeatedly tempted to have classes implement IDisposable
to be able to abuse this mechanism in ways it's not intended for. For example, one could implement classes to handle nested contexts like this:
class Context : IDisposable
{
// Put a new context onto the stack
public static void PushContext() { ... }
// Remove the topmost context from the stack
private static void PopContext() { ... }
// Retrieve the topmost context
public static Context CurrentContext { get { ... } }
// Disposing of a context pops it from the stack
public void Dispose()
{
PopContext();
}
}
Usage in calling code might look like this:
using (Context.PushContext())
{
DoContextualStuff(Context.CurrentContext);
} // <-- the context is popped upon leaving the block
(Please note that this is just an example and not to the topic of this question.)
The fact that Dispose()
is called upon leaving the scope of the using
statement can also be exploited to implement all sorts of things that depend on scope, e.g. timers. This could also be handled by using a try ... finally
construct, but in that case the programmer would have to manually call some method (e.g. Context.Pop
), which the using
construct could do for thon.
This usage of IDisposable
does not coincide with its intended purpose as stated in the documentation, yet the temptation persists.
Are there concrete reasons to illustrate that this is a bad idea and dispell my fantasies forever, for example complications with garbage collection, exception handling, etc. Or should I go ahead and indulge myself by abusing this language concept in this way?
So in asp.net MVC views, we see the following construct:
using(Html.BeginForm())
{
//some form elements
}
An abuse? Microsoft says no (indirectly).
If you have a construct that requires something to happen once you're done with it, IDisposable
can often work out quite nicely. I've done this more than once.
"Is it an abuse of the IDisposable
interface to use it this way"? Probably.
Does using using
as a purely "scoping" construct make for more obvious intent and better readability of code? Certainly.
The latter trumps the former for me, so I say use it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With