views:

299

answers:

4
+5  Q: 

Dispose question

When you have code like:

Bitmap bmp = new Bitmap ( 100, 100 );
Graphics g = Graphics.FromImage ( bmp );

Pen p = new Pen ( Color.FromArgb ( 128, Color.Blue ), 1 );
Brush b = new SolidBrush ( Color.FromArgb ( 128, Color.Blue ) );

g.FillEllipse ( b, 0, 0, 99, 99 );    
g.FillRegion ( b, pictureBox1.Region );

pictureBox1.BackColor = Color.Transparent;
pictureBox1.Image = bmp;

Do you have to dispose the pen and brush? What about bmp and the g?

My main question is, if these were to be disposed manually, why don't they get disposed as soon as they get out of the scope? Is that what would happen, if you didn't dispose them manually? Is it the delay that makes people do this manually?

+1  A: 

Dispose is used to dispose of unmanaged resources.

So, as a rule of thumb, I wrap any instantiations of IDisposable objects in a using statement, so I don't have to worry about what unmanaged resource a Pen has.

Aaron Daniels
+6  A: 

Yes, you have to dispose them - not just pen and brush, but also Bitmap and Graphics.

They don't get disposed when they're out of scope because the variables themselves are references, not objects, and C# compiler doesn't know whether the ownership still belongs to those references or not (e.g. FillEllipse could, in theory, remember the reference it's given, and try to use it at some later moment - remember that language compiler doesn't have any special knowledge of library semantics!).

If you want to indicate that ownership is restricted to that scope, you use the using statement:

using (Bitmap bmp = new Bitmap ( 100, 100 ))
using (Graphics g = Graphics.FromImage ( bmp ))
using (Pen p = new Pen ( Color.FromArgb ( 128, Color.Blue ), 1 ))
using (Brush b = new SolidBrush ( Color.FromArgb ( 128, Color.Blue ) ))
{
    g.FillEllipse ( b, 0, 0, 99, 99 );    
    g.FillRegion ( b, pictureBox1.Region );
}

This will make the compiler insert calls to Dispose automatically as needed, ensuring that all objects are disposed once the corresponding using scope is left (whether normally, by control transfer such as return or break, or an exception).

If you come from a C++ background, using in C# is directly analogous to a const std::auto_ptr, except that it's a language construct here, and can only be used for local variables (i.e. not for class fields).

Pavel Minaev
Really? Interesting. I've never seen that for anything but the Graphics object before. Is there an MS site that talks about this in more detail?
Ryan
It's true that you should call `Dispose` or employ the `using` statement, but it's not true that the `Pen` will otherwise not be disposed out of scope because some API might be using it. `Pen` has a finalizer, which will run at some unspecified time after it becomes unreachable (for a short-lived object it can be pretty soon after), and when that happens, it does the equivalent of `Dispose`.
Daniel Earwicker
See: http://msdn.microsoft.com/en-us/library/system.drawing.pen.dispose.aspx - "call Dispose... Otherwise, the resources it is using will not be freed until the garbage collector calls the Pen object's Finalize method."
Daniel Earwicker
Earwicker, these objects are gonna be added to the Finalization queue only after GC has started, right?
Joan Venge
Ryan, if it implements `IDisposable`, then someone somewhere should dispose it. In this case, it's pretty obvious that no code but ours can do this. Earwicker is correct that there is also a finalization mechanism to clean up if you forget to dispose, but as it is undetermined where it kicks it (it may even happen as late as your application shutdown), you may get severe leaks if you do not dispose explicitly; in general, relying on finalizers for such cases is a very bad idea.
Pavel Minaev
@Pavel, I tried Disposing the "bmp" too, but it causes an exception when it's disposed after assigned to the Image property of a control.
Joan Venge
Well, naturally, because if you assign it to the `Image` property, then control uses it, and you shouldn't dispose it while it's in use.
Pavel Minaev
Henk Holterman
+3  A: 

C# doesn't "destruct" or dispose of things as soon they go out of scope.

Those classes will most likely automatically free the unmanaged resources that they hold on to in their special Finalizer method, which will be called when they are garbage collected at an indeterminate time after going out of scope.

But to rely on that is to rely on something that is out of your control, and might not happen for a while.

If the class implements IDisposable, best practice is for you to manually call Dispose() somewhere, or preferably wrap it in a using block. That way you can be sure that:

A. The unmanaged resources are definitely being freed.

B. The unmanaged resources are freed as soon as possible.

frou
+2  A: 

Hi there.

I know other people have put code examples here, but I started so I'll finish:

using (Bitmap bmp = new Bitmap(100, 100))
            {
                using (Graphics g = Graphics.FromImage(bmp))
                {
                    using (Pen p = new Pen(Color.FromArgb(128, Color.Blue), 1))
                    {
                        using (Brush b = new SolidBrush(Color.FromArgb(128, Color.Blue)))
                        {
                            g.FillEllipse(b, 0, 0, 99, 99);
                            g.FillRegion(b, pictureBox1.Region);

                            pictureBox1.BackColor = Color.Transparent;
                            pictureBox1.Image = bmp;
                        }
                    }
                }
            }

I always use 'Using' in my code since it calls Dispose() on your object automatically, even if there is an exception raised in the Using block. I use it a lot for SharePoint projects (but that's another story...).

Cheers. Jas.

Jason Evans
Correct, but it is (becoming) customary to fold multiple usings to 1 brace pair, like in Pavels sample.
Henk Holterman
Cool, I haven't seen that technique before. Think I'll start using it (no pun intended) from now on :)
Jason Evans