Sunday, March 30, 2008

Things you MUST dispose

When the .NET Framework instantiates an object, it allocates memory for that object on the managed heap. The object remains on the heap until it's no longer referenced by any active code, at which point the memory it's using is reclaimed by the Garbage Collector (GC). Before the GC deallocates the memory, the framework calls the object's Finalize() method, but developers are responsible for calling the Dispose() method.

If you want to read more about GC, please take a look on this article: How the Garbage Collector works.

Dispose GUI elements

  • Dialog forms. In .NET, a dialog form is a form opened by calling the ShowDialog() method. Unlike modeless forms, the Close method is not called by the .NET Framework when the user clicks the close form button of a dialog box or sets the value of the DialogResult property. Instead the form is hidden and can be shown again without creating a new instance of the dialog box. Because a form displayed as a dialog box is not closed, you must call the Dispose() method of the form when the form is no longer needed by your application.
  • GDI+ resources. The GDI+ resources, like: pens, brushes and fonts, need to be disposed because they encapsulate GDI+ handles in them and GDI+ is build in C++ (unmanaged code). To release the GDI+ resources, we must call the Dispose() method for each of them.

    The proper usage is to create, use and dispose of an item in the right place. For example:

    C# .NET

    void override OnPaint(PaintEventArgs e)

    {

        Pen p = new Pen(Color.Blue, 1); // create

        e.Graphics.DrawLine(p, 0, 0, 20, 20); // use

        p.Dispose(); // dispose

    }


    Don't use GDI+ resources like this:

    C# .NET

    g.DrawLine(new Pen(Color.Blue, 1), 0, 0, 20, 20);


    The Pen object in this case is created inline and never disposed of. However, when using one of the ready-made pens from Pens or SystemPens, you must never dispose the object! This is also true for ready-made brushes.

    The Graphics object, if is returned by Control.CreateGraphics() method, must be also disposed as soon as it is not needed anymore. If the Graphics object is accessed thru PaintEventArgs you don't have to call Dispose() because .NET will handle that for you. You can read more about GDI+ in this article: GDI+ Windows rendering API.
  • Icon.FromHandle. When using the Icon.FromHandle() method you must dispose of the resulting icon using the DestroyIcon method in the Win32 API to ensure the resources are released.

    C# .NET

    [DllImport("user32.dll", CharSet = CharSet.Auto)]

    extern static bool DestroyIcon(IntPtr handle);

     

    private void GetHicon_Example(PaintEventArgs e)

    {

        // Create a Bitmap object from an image file.

        Bitmap myBitmap = new Bitmap(@"c:\FakePhoto.jpg");

     

        // Draw myBitmap to the screen.

        e.Graphics.DrawImage(myBitmap, 0, 0);

     

        // Get an Hicon for myBitmap.

        IntPtr Hicon = myBitmap.GetHicon();

     

        // Create a new icon from the handle.

        Icon newIcon = Icon.FromHandle(Hicon);

     

        // Set the form Icon attribute to the new icon.

        this.Icon = newIcon;

     

        // Destroy the Icon, since the form creates

        // its own copy of the icon.

        DestroyIcon(newIcon.Handle);

    }

Dispose data sources

  • Database connections. Dispose any database connection you don't need anymore to ensure no resources are being held by it. Also, the Dispose method of a connection object automatically calls its Close method.
  • Stream objects. This includes files and memory streams, anything inheriting from the Stream class. Calling Dispose allows the resources used by the stream to be reallocated for other purposes. Before releasing all the resources, this method disposes the stream, by writing any changes to the backing store and closing the stream.
kick it on DotNetKicks.com

10 comments:

Dylan Greene said...

Is there a good way to automate a dispose check during build?

Admin said...

It seems that Visual Studio 2005 Team System ships with a Code Analysis rule called "CA2000 DisposeObjectsBeforeLosingScope". Unfortunately, the VS 2005 standard edition and the FxCop don't have it and I guess it is difficult to implement as custom rule for FxCop.

Here is a post that might help you:

http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1688220&SiteID=1

Jesse Foster | jf26028 said...

A good thing to add to this list is wcf channels because you cant just throw them in a using statement. You have to handle them with a try/catch/finally, or some simular approach.

Jesse Foster | jf26028

Admin said...

Thanks for this tip. I will update my post as soon as I have some time. All my post are open, so I will update each when new info comes in.

Anonymous said...

Doesn't FXCop recognise which classes implement IDisposable() and suggest you to use "Using"? I recall seeing something like that, but I may be wrong.

Niki said...

I doubt this list is (or ever will be) complete - dispose anything that implements IDisposable. That includes, among other things, syncronization objects, threads, processes, sockets and listeners, http/ftp connections, printers and propably lots of other classes i didn't think of...

Admin said...

Niki is right. But sometimes you don't have to dispose an object because .NET will do it for you (please see Graphics object provided by PaintEventArgs vs CreateGraphics() method). I will try to provide more details on this post.

Anonymous said...

Hello,

About the WinForms (dialog) issue: this isn't true.

Start a childform as a dialog and set a breakpoint in the Dispose method, close it and call GC.Collect(). You'll notice your breakpoint gets hit.

Paul said...

I have been looking for some info about Things you MUST dispose, and wow I have no idea that in the web were so many blogs related to generic viagra, but anyways, thanks for sharing your inputs and have a nice day.

Anonymous said...

i am sure that this post can be stolen from a book depend on c#