Search code examples
c#winformsgraphicsdisposeidisposable

Disposing Graphics objects


I am confused by disposing mechanisem of graphical objects. What is the best way to dispose objects such as fonts and pens? And what could be the best practice to when instantiate/dispose them? I mean as fields in class or variables inside methods?

For example, I have a class like the following code. I have some fonts and pens that is used eveywhere in the class, so instead of creating them each time inside calling methods I just create them as fields. Does this improve performance?

public class PackageDrawer : IDisposable
{
   Font font1 = ....
   Font font2 = ....
   Font font3 = ....
   Pen  pen1 = ...
   Pen  pen2 = ...
   Pen  pen3 = ...

   public Bitmap Draw()
   {
       //use fonts and pens here
       //also they are being user in more methods
   }

   ~PackageDrawer()
   {
       Dispose();
   }

   public void Dispose()
   {
       font1.Dispose();
       //And dispose other stuff...
   }
}

Solution

  • What is the best way to dispose objects such as fonts and pens?

    The best and only way is to call Dispose() You should dispose of them when you no longer need them.

    And what could be the best practice to when instantiate/dispose them?

    This all depends on your implementation. In most cases, it's best to create and destroy them as soon as you are done with them. It all really depends on how your client code is implementing the PackageDrawer object and it's methods that might access those.

    You might want to read up on IDisposable here on StackOverflow. From what you posted, you can remove the ~PackageDrawer() finalizer override and simply just make a Dispose() method. You may also want to make the Dispose method virtual in case you derive any classes from this one.

    Also, there isn't anything preventing from Dispose() to be called multiple times on your object so you will want to add a private tracking boolean to make sure that it won't try and Dispose() more than once. Also, always do a null check on an object before trying to call Dispose() to avoid a NullReferenceException.

    private bool _isDisposed;
    
    public void Dispose()
    {
        Dispose(true);
    }
    
    protected virtual void Dispose(bool disposing)
    {
       if (_isDisposed)
          return;
    
       if (disposing)
       {
           if (font != null)
               font.Dispose();
       }
    
       _isDisposed = true;
    
    }