views:

49

answers:

5

I understand it is best practise to call Dispose() on instances of Pen and Brush, except if they've been set to the system-predefined values (eg. System.Drawing.Brushes, System.Drawing.Pens or System.Drawing.SystemBrushes)

Trying to dispose a system-defined resource results in an exception being thrown.

It doesn't appear to be obvious how you can detect (apart from wrapping the Dispose() call in a try/catch) whether one of these resources is referencing a system-defined or user-defined value.

A: 

I could be wrong but I think you can assume that the lifetime (and the disposal) of the predefined brushes and pens is not your app's responsibility and will be handled by the system.

In short: don't call Dispose on the predefined stuff. :)

lzcd
Yes, that's what I want to avoid - my question is how to know if calling Dispose() is ok or not. I'm interested if there's anything better than calling Dispose() inside a try/catch, because I'd prefer to avoid the 'cost' of having an exception thrown.
David Gardiner
@Whoever: Why the downvote? **Lzcd** is correct. You can verify through Microsoft's source code or *.NET Reflector*.
AMissico
A: 

Only thing come in mind is to have a practice do not use System pens/brushes as parameters to methods.

serhio
A: 

There is no requirement to call Dispose. The purpose of garbage collection is to eliminate these kinds of requirements.

One of the main purposes of IDisposable is to allow a class to clean up unmanaged resources in resource-limited environments. If you do not call the dispose method, the unmanaged resouces of the class will be cleaned up once the object is finialized and disposed during garbage collection.

If you "must" call dispose and you do not know if the brush instance is a "system-" or a "normal-" brush then you will have to use a try...catch block.

  • It is not needed to call dispose on SystemBrushes and SystemPens because the GDI+ Library will take care of these resources.
  • Okay to dispose of SystemFonts and SystemIcons.

The Remarks section of the class will make note of if there is a requirement to call the Dispose method. If the Remarks section recommends to call the Dispose method, then I will do it.

In general, I do not call dispose on pens and brushes. If I have a graphic-intensive application or class then I will cache instances of the pens and brushes I need. I use them throughout the life of the application or class. If I didn't do this then graphics painting performance will suffer trying to create and dispose all those ojects so many times and so frequently. (Hm...now that I think about it, performance is probably why we cannot dispose of SystemBrushes and SystemPens, yet can dispose of SystemFonts and SystemIcons. Even the framework caches SystemBrushes and SystemPens.)

AMissico
Thanks for your comments, however I think it needs clarifying that the GC will only clean up unmanaged resources if you have a finalizer declared - it doesn't automatically call your Dispose() method. Applications can pre-empt the GC by calling Dispose() which should then allow it to be GC'd sooner.Otherwise, I suspect you are right and try/catch is the only option if there is no other way of knowing what the brush/pen was set to.
David Gardiner
Note that nearly all GDI+ based classes implement the `IDisposable` interface because of their use of unmanaged resources. Therefore, in regards to this question and answer, `Dispose(disposing=False)` will always be called through the `Finalize` method. Regardless, there is still no requirement to call `Dispose`.
AMissico
The framework automatically calls the `Dispose` methods of any created `SystemBrushes` and `SystemPens` objects when the GDI+ library is shut-down.
AMissico
I did not use the word "automatically". I left out the details because this is not part of the question/answer.
AMissico
Unfortunately, the remarks in this case are incomplete. Look at the sample code in the documentation -- it does explicitly call Dispose, as it should.Actually, that first statement works as a general rule. If remarks were that complete, wouldn't we have less need for sites like this one? :)
Ari Roth
A: 

Just for completeness, using Reflector I see that the System.Drawing.Pen and System.Drawing.SolidBrush classes have a private field named 'immutable'.

This field appears to be set to true when the object refers to a system-defined resource, so you could use reflection to carefully check the value of this field to decide whether to call Dispose() on it.

David Gardiner
+2  A: 

First of all, you always should Dispose of brushes when you can and not leave it up to the garbage collector. While GDI will eventually get around to taking care of that stuff (assuming the library gets shut down properly), there's no telling when that may be. In fact, my understanding is that brush handles stick around for the long-term. Over the course of a long-running application, you're looking at a de facto memory leak. Sure, in a small application that won't run for long, or in one that only rarely creates brushes, you can let the system handle it, but that strikes me as sloppy.

As a general rule, whenever I create a brush I do so in a using statement. That automatically calls dispose on the brush without having to worry about it. As an added bonus, since you create the brush inside the statement you know that it's not a predefined brush. Any time you create and use a non-predefined brush, wrap the block in a using and you don't have to worry about it at all. In fact, you don't even need to explicitly call Dispose, since the block will do so even in the case of an exception.

Ari Roth