0

My application has two distinct forms;

  1. the main application form,
  2. another one showing warnings, info, error, etc. (only when needed).

In form 1 (the application's main form), second form is called in various lines, as below;

FormMain:

...
if (sth_goes_wrong) {
    this.formWarn = new FormWarn("explanatory message...");
    this.formWarn.Dispose(); // <- this is the line in question
}
...

FormWarn:

internal class FormWarn : Form {
    ...
    public FormWarn(String msg) {
        this.SetupStuff();
        this.btnOk.Click += FormWarn_BtnOkClick;
        ...
        this.ShowDialog();
    }

    private FormWarn_BtnOkClick(Object sender, EventArgs e) {
        ...
        this.Close();
    }
    ...
}

The warning form in shown as "dialog" and the user, after reading the message, is supposed to press a button (btnOk) which sends the program flow to a line with Close() method.

My question is; does that Close() method (in the FormWarn class) take care of freeing resources or do I need to use a Dispose() method after returning back to the main form?

ssd
  • 2,340
  • 5
  • 19
  • 37
  • @EdPlunkett: `FormWarn` is of type `Windows.Forms`. I mean, it's class is defined as `internal class FormWarn : Form {...`. So, yes; it's an IDisposable type. – ssd Nov 05 '19 at 17:39
  • 2
    The form class can dispose itself without help, unless it is displayed with ShowDialog(). Then it doesn't, retrieving the dialog properties on a disposed form object is too risky. You always use `using` in that case, never Dispose(). – Hans Passant Nov 05 '19 at 17:47
  • 3
    [Do I need to Dispose a Form after the Form got Closed?](https://stackoverflow.com/a/39501121/3110834) – Reza Aghaei Nov 05 '19 at 17:50

1 Answers1

0

The general rule is anything which implements IDisposable should be disposed. This includes forms, since the base Form is IDisposable. Furthermore, steps should be taken to ensure disposal even in the event of an exception. Therefore, the better pattern typically looks like this:

if (sth_goes_wrong) {
    using (var formWarn = new FormWarn("explanatory message..."));
    {
        formWarn.ShowDialog();
    }
}

Note I did not use the member variable and showed the form using a blocking dialog.

Alternatively, you can continue using the member variable. However, in that case you need to override the current form's Dispose() method to also dispose your formWarn instance, if it exists, and the code in question should look like this:

if (sth_goes_wrong) {
    this.formWarn = this.formWarn ?? new FormWarn();
    formWarn.Message = "explanatory message..."; 
    formWarn.Show();
}

where you also added that new Message property allowing you to update an existing instance.

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
  • Ok, got it. Just another question, if you don't mind: This `FormWarn` is shown, say, 10 to 20 times in one hour. In that case, which option should I prefer? Relying on the garbage collector, should I close and dispose the form every time or is it better to create once and continue showing the same form by changing the message only? – ssd Nov 05 '19 at 18:16
  • 1
    If you're comfortable with a modal dialog, I would create new instances, as this is unlikely to drive overall performance and the code is simpler. If you are not comfortable with a modal dialog for this situation, I would create a default/shared instance. Additionally, for a long-running app, you _can_ ignore the need for disposal of a single instance that should be available for the entire lifecycle of the app. Or rather, you can count on the tearing down of the full app to finally dispose this instance, rather than your own code. But you must also be very careful this really holds true. – Joel Coehoorn Nov 05 '19 at 18:20