2

I have the following code in my program:

//Dialog Form Class

public int Age;

private void goButtonClick(object sender, EventArgs e)
{
     Age = trackBar1.Value;
     Close();
}

//Main Form Class

DialogForm df = new DialogForm();
df.ShowDialog();
df.Dispose();
if(df.Age >= 18)
{
    //do stuff
}

Surprisingly, I thought I was going to need a way to access df.Age since it would have been disposed by the Close method but surprisingly, I could access this value. I assumed this was some kind of intelligence of the garbage collector so I added df.Dispose() before calling df.Age just to see what will happen, but I could still access it. So I got confused? Why is this happening? When exactly does an item get disposed?

rtuner
  • 2,362
  • 3
  • 25
  • 37
  • 3
    `Dispose` [does not trigger](http://stackoverflow.com/a/2344271/21567) a garbage collection. – Christian.K Sep 17 '12 at 12:33
  • *When exactly does an item get disposed?* When the `Dispose` method is called. But please don't mistake disposing for garbage collecting. – sloth Sep 17 '12 at 12:35

5 Answers5

5

Usually, the answer is "when your code calls .Dispose()", which usually means "when it leaves the using block", however some code has additional things that cause it to be disposed. For example, on a winform, if you use the Show() method to display it, then it is disposed when the form is closed.

HOWEVER! For a form shown via ShowDialog(), this is not done; after all, it is modal, so the expected lifetime is obvious:

using(var df = new DialogForm())
{
    df.ShowDialog();
    if(df.Age >= 18)
    {
        //do stuff
    }
}

or better:

int age;
using(var df = new DialogForm())
{
    df.ShowDialog();
    age = df.Age;
}
if(age >= 18)
{
    //do stuff
}

You might also want to check the return value of ShowDialog() to see whether it was cancelled etc.

But to answer your question directly: the form in your question is never properly disposed. The IDisposable.Dispose() method is never called.

The garbage collector will find it at some point, and will call the finalizer, which will call the inbuilt Dispose(bool) pattern, but that is an implementation detail of winforms, and is not proper disposal.

See also MSDN for ShowDialog():

When a form is displayed as a modal dialog box, clicking the Close button (the button with an X at the upper-right corner of the form) causes the form to be hidden and the DialogResult property to be set to DialogResult.Cancel. Unlike non-modal 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 hidden instead of closed, you must call the Dispose method of the form when the form is no longer needed by your application.

Hans Kesting
  • 38,117
  • 9
  • 79
  • 111
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • exactly the answer I was looking for. Thanks! – rtuner Sep 17 '12 at 12:43
  • The confusing thing though is that MSDN says you call Dispose method when it is no longer needed but you say it is never *properly* disposed? – rtuner Sep 17 '12 at 12:45
  • @rtuner because in the code in your question you **haven't** called `Dispose()`, nor have you used a `using` block. Thus: it is never disposed. It is *your job* to call `Dispose()` on this, one way or another. – Marc Gravell Sep 17 '12 at 12:47
  • Hmm, I mentioned I called `dispose` manually in my code. See the edited version. It doesn't affect whether I can access it :/ ? – rtuner Sep 17 '12 at 13:01
  • 1
    @rtuner right; with your edit, it all comes down to how `.Age` is implemented. If that is backed by a *field* then it will be fine; if it is backed by a *control*, then since the child control will have been disposed, it *could* error. The important thing, though, is that disposal is **unrelated** to collection. Do you see what I mean? – Marc Gravell Sep 17 '12 at 13:23
  • Thanks. If I understand what you mean, you are saying that since the Age is a field and not an object, it can still be accessed since dispose doesn't actually destroy it? – rtuner Sep 17 '12 at 13:35
3

If you are able to call df.Age, this means you're holding the reference to the object (df is just a reference). This in turn means, garbage collector won't collect it, hence the value is still there.

And Dispose() does not call garbage collector, nor it removes the reference. Dispose is for situations where your objects needs to free some resources explicitly, and you expose this method so that it can be called (not by GC).

Bartosz
  • 3,318
  • 21
  • 31
1

This is because you use ShowDialog(..) call.

In this case Dispose on the form is not called by CLR, to get you a way to retrieve at least dialog result from the form. So this is the only case when you need to call Dispose(..) esplicitly after the close.

More on this you can read on community content Form.ShowDialog

Tigran
  • 61,654
  • 8
  • 86
  • 123
0

The garbage collector will only collect the memory where nothing holds a reference to that object. So, in your case, you still have a reference to the dialog in your main window until the point the method referencing the dialog ends.

Barracoder
  • 3,696
  • 2
  • 28
  • 31
0

There is no magic involved with Dispose. It's just a method call.

Erix
  • 7,059
  • 2
  • 35
  • 61