CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Steve Hebert's Development Blog

Steve's Blog - From .Net to dotMath and everything in between.

managing disposable objects in a graphical app

Whenever I deal with disposable objects, I always wrap them in a using() statement religiously. 

Now that I am writing a graphical application where the drawing engine may paint on different surfaces (24-bit bitmap vs. black and white), I've abstracted a 'Pallet' object with concrete implementations for each Pallet type. This allows me to abstractly ask the Pallet for things like a "BackgroundBrush" or "ShadowBrush". 

My dilemma is this:  in the BackgroundBrush() method I believe it's better (performance-wise) to say something like:

      if( _backgroundBrush == null ) _backgroundBrush = new SolidBrush(....);
      // test nullness and throw exception here if necessary
      return _backgroundBrush;

The problem arises if the client code makes the following call:

   using( Brush backgroundBrush = pallet.BackgroundBrush)
   {
      // do something with brush
   }

My cached brush is now invalid for subsequent calls to BackgroundBrush.  This exception to normal coding practice has to be communicated and I know that it's just asking for trouble. 

Since the creation of brushes take time, I'd rather have the Pallet object implement IDisposable.  When the system needs the picture drawn, it creates the Surface object and the pallet and wraps these with using() statements.  Using this method, each gdi+ object is created at the last possible moment and disposed at the last responsible moment.  This caching isn't a problem in my usual apps with databases because the real time it takes to create a connection is cached by the system - therefore I always dispose every connection and downstream object.  But this need is different.  I just don't like having a bunch of objects being returned that implement IDisposable but shouldn't have their .Dispose() function called - it just feels like a really bad code-smell waiting to happen .

I suppose I could solve the problem by returninf an abstracted object, thereby pushing the actual object brush up into the framework , but I'm not there yet in terms of justifying that object. 


Published Jul 19 2005, 09:40 AM by shebert
Filed under:

Comments

Scott Allen said:

If you are asking for a property of the pallet (pallet.BackgroundBrush), then it should be clear that Pallet still owns the brush, it's not the client's object to dispose.

For method calls (pallet.GetBackgroundBrush()) - I think it's clear the burden of ownership has been given to the caller.

# July 19, 2005 10:03 AM

shayne said:

How about a decorator?
# July 19, 2005 12:11 PM

shebert said:

Great point Scott.

I will definitely keep the decorator/wrapper pattern in mind if I can associate behaviors other than garbage collection to the implementation.

Thank you both for the feedback!
# July 20, 2005 8:50 AM
Check out Devlicio.us!