How To Dispose Members From Forms

When you create a new Form (or UserControl for that matter), Visual Studio creates it as a partial class, with the designer-generated code going into the *.Designer.cs file. One other piece of code that also goes into the designer code is an override of System.ComponentModel.Component.Dispose(bool), which contains the code to dispose the form and its contained components. It always looks like this:

 protected override void Dispose(bool disposing)
{
    if (disposing && (components != null))
    {
        components.Dispose();
    }
    base.Dispose(disposing);
}

It's a bit unfortunate that this method is being overridden, because it makes it more difficult to add your own dispose logic to the form, since you can't override the method once more in the same class - remember that the form code that you control is only part of the class definition. You could obviously edit the designer file directly, but that's not recommended.

Then what can you do if you need to perform some extra dispose logic in your Form? This need can easily arrive if one of your member variables implement IDisposable, in which case you really should dispose of it when the Form disposes. Imagine you have the following IDisposable class:

 public class MyDisposable : IDisposable
{
    private string message_;
 
    public MyDisposable(string message)
    {
        this.message_ = message;
    }
 
    #region IDisposable Members
 
    public void Dispose()
    {
        MessageBox.Show(this.message_);
    }
 
    #endregion
}

You now want to have a MyDisposable member variable in your Form, and you need to dispose of it when the Form disposes:

 public partial class MyForm : Form
{
    private MyDisposable myDisposable_;
 
    public MyForm()
    {
        InitializeComponent();
 
        this.myDisposable_ =
            new MyDisposable("Goodbye, World");
    }
}

When you run the application and close the Form, the Form is being disposed, but you never see the goodbye message because myDisposable_ is not disposed. The Dispose method in the designer code handles the dispose logic for the form, and it knows nothing about the myDisposable_ member variable.

It does, however, Dispose of its components member, and since this is an IContainer, the problem would be solved if you could add myDisposable_ to the container. Unfortunately, IContainer only accepts IComponent instances, and if you may not want to implement IComponent on MyDisposable.

Part of the contract of IComponent is that an implementation must have a default constructor, and for API design reasons, you may not find that acceptable for your IDisposable type - for some reason, I don't think that's an acceptable change for MyDisposable.

What you can do, however, is to add an instance of this little class to the container:

 internal class Disposer : Component
{
    private Action<bool> dispose_;
 
    internal Disposer(Action<bool> disposeCallback)
    {
        this.dispose_ = disposeCallback;
    }
 
    protected override void Dispose(bool disposing)
    {
        base.Dispose(disposing);
 
        this.dispose_(disposing);
    }
}

From your Form code, you'll need to wire up a new instance of Disposer with a delegate which will contain the real dispose logic. When used in MyForm, it now looks like this:

 public partial class MyForm : Form
{
    private MyDisposable myDisposable_;
 
    public MyForm()
    {
        InitializeComponent();
 
        this.myDisposable_ =
            new MyDisposable("Goodbye, World");
        this.components.Add(new Disposer(this.OnDispose));
    }
 
    private void OnDispose(bool disposing)
    {
        this.myDisposable_.Dispose();
    }
}

Notice that I have added a new Disposer instance that points back to the new OnDispose method, which then implements all the dispose logic not handled by the designer code. Now, when I run the application and close the Form, I get the expected MessageBox.

This technique is generally usable whenever you need to dispose of a member variable, but otherwise can't because the designer code already overrides the Dispose method. However, I only recommend this approach if your member variable doesn't also implement IComponent.

If the you have control over the member variable's class and don't mind having a default constructor, I recommend that you instead implement IComponent (the easiest way to do that is by deriving from System.ComponentModel.Component like I did with the Disposer class). This will generally give you a nicer design-time experience, since you can now just drag the component from the toolbox to the design surface, and the designer (Visual Studio) will automatically add it to the components member variable, and thus it will be disposed together with all the other components in the container.

Both approaches also work if you are creating a UserControl, although there, you'll probably need to instantiate the components member variable yourself.