12

So in my apps, I tend to create new instances of forms on the fly, then use Form.Show() to display them (non modal).

private void test_click(object sender, EventArgs e)
{
    var form = new myForm();
    form.Show();
}

However, Code Cracker tells me that these forms should be disposed. So, I wrapped them with the "using" statement, but then they close immediately after opening.

using (var form = new myForm())
{
    form.Show();
}

I don't want to use Form.ShowDialog(), because in a few instances I'm opening new windows that only show reports; I don't need them to be modal.

Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
javon27
  • 316
  • 2
  • 10
  • 9
    Answer is clear. "Code Cracker" misguides you. Don't use `using`.... Dispose the form whenever it is appropriate... – L.B Sep 14 '16 at 21:59
  • I have to agree with @L.B here - closing the window is the correct thing for Dispose() to do. By definition, a correctly-implemented Dispose() method should leave the disposed object in an unusable state. – EJoshuaS - Stand with Ukraine Sep 14 '16 at 22:08
  • 1
    Reading this [thread](https://social.msdn.microsoft.com/Forums/windows/en-US/cc4acf77-6e7e-46a6-992d-702e314acbdf/howwhen-to-call-dispose-when-using-a-modeless-dialog?forum=winforms) seems to indicate that I shouldn't have to worry about disposing. Non modal forms are automatically GC'd. I tested while watching Task Mananger, and memory is reclaimed. – javon27 Sep 14 '16 at 22:13
  • I just checked the implementation. Dispose isn't always called internally, but all it does is remove the form from its container and raise the disposed event. All the resources are already released in other ways, and nothing happens on garbage collection. (Of course, that doesn't mean you shouldn't call dispose, since this could change in the future. But it means you don't have to worry about it right now.) – Cameron Sep 14 '16 at 22:16
  • 1
    @Cameron Thanks for checking. So, I guess I'm left wondering, what do other people do? – javon27 Sep 14 '16 at 22:20
  • @javon27 do it in the unload, thats the best place. – loneshark99 Sep 15 '16 at 00:43
  • @loneshark99 you don't need to call dispose for a form which you opened using `Show` method. Read my answer for more details. – Reza Aghaei Sep 15 '16 at 00:47
  • @reza-aghaei just because it marked as answer doesnt mean its right – loneshark99 Sep 15 '16 at 00:49

4 Answers4

28

Do I need to Dispose a Form after closing the Form?

When you show the form using Show() you don't need to dispose it, because it will dispose after close. But when you show form using ShowDialog(), you need to dispose the form, because it won't dispose after closing.

When you close a Form, a WM_CLOSE message will be sent to the window. If you take a look at source code of WmClose method which handles WM_CLOSE message, you will see:

  • For modal forms (which you showed using ShowDialog), the Dispose method will not be called and the form exists after closing and you can use its properties to get some data or you can show it again.

  • For non-modal forms (which you showed using Show), after the form got closed, the Dispose method will be called.

So here is the conclusion:

  • When you show a form using Show method you don't need to (and you can't) call Dispose. The form will be disposed itself after got closed.

  • When you show a form using ShowDialog you need to call Dispose manually. A good practice is use modal forms in a using block.

Example

To show a modal dialog, as a best practice use a using block:

//form will be disposed after the using block
using (var f = new MyForm())
{
    if (f.ShowDialog() == DialogResult.OK)
    {
        //Your logic to handle OK here
    }
}

For a non-modal dialog, show and forget about it:

var f = new MyForm();
f.Show();
Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
13

Hmm, "code cracker" appears to be a very appropriate term for that tool, its advice certainly made you write code that breaks your program. Golden Rule is to never trust IDisposable advice from a static code analysis tool, none of them ever have sufficient insight in code execution. They can never figure out which Dispose() call gets the job done.

What it cannot see is that the Form class already knows how to dispose itself. It is very easy for it to do so, the object becomes unusable when the window closes. When there is no more window then there's no reason to keep using the Form object. A luxury that isn't otherwise very common in .NET but certainly inspired by very smart programmers that worked for Xerox 45 years ago.

There is only one special rule you have to keep in mind, it does not dispose itself when you use ShowDialog() to display the window. That was intentional, it makes retrieving the dialog results too risky. Using the using statement for a ShowDialog() call is very easy to do, the call does not return until the window is closed.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • You're right on all accounts. I just hate seeing all the squiggly lines from Code Cracker, but at the same time don't want to add suppression rules. I also don't want to get rid of it completely because it provides plenty of insights for this junior developer. – javon27 Sep 14 '16 at 22:32
  • 1
    Just turn the specific analysis rule off, it doesn't help you at all. Or learn to not trust tools too much, makes you senior :) – Hans Passant Sep 14 '16 at 22:34
1

You could implement somekind of forms manager that will subscribe to the OnFormClosedEvent for each form it shows, it can then dispose them... something like:

public class FormManager
{
    public T ShowForm<T>()
        where T : Form, new()
    {
        var t = new T();
        t.OnFormClosing += DisposeForm;
        return t;
    }

    void DisposeForm(object sender, FormClosedEventArgs args)
    {
        ((Form)sender).Dispose();
    }
}

You could even go so far as to implement IDisposable and dispose all non-disposed forms when the manager is disposed :)

Scott Perham
  • 2,410
  • 1
  • 10
  • 20
0

So according to the answer over at MSDN, non modal forms are automatically Disposed whenever you close them.

I decided to test this by opening my test form multiple times and closing them. I even opened multiple instances at the same time. After a second or two, the memory used by these forms were reclaimed, which would indicate that they were being disposed properly.

javon27
  • 316
  • 2
  • 10
  • Actually this indicates that the GC is reclaiming the memory, not that `Dispose` is being called. In this case `Dispose` doesn't clean up any native resources, so all the memory is managed by the GC, and it gets released regardless of whether `Dispose` is called or not. – Cameron Sep 14 '16 at 22:26