I'm talking about a WinForms Form here, so this doesn't apply to WPF or GTK or any other tool kit (which is not to say they don't have the same behavior, just that I don't know).
When you open a Form with Form.Show() it gets disposed automatically when the user closes it or when you programmatically call the Close() method. However, when you open a Form with Form.ShowDialog() it doesn't get disposed when the user closes it, nor when you programmatically close it. It just gets hidden. Presumably this is so you could re-show it if you wanted to. The downside of this is you have to dispose it manually.
You may be thinking that this isn't a big deal because the garbage collector will take care of it for you when the variable goes out of scope. This is not the case. If you don't call the Dispose method that form, and anything referenced by the form, will remain in memory until your program ends.
Because of this, my best practice recommendation is anytime you're opening a Form with ShowDialog, consider doing some like this:
using( SomeDialog sd = new SomeDialog() )
If you can't constrain the scope of your form to just one method then you're stuck remembering to dispose it before you finish with it.
This behavior is, at least to me, somewhat unexpected. However, it is fully documented in MSDN:
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 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.