Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Access a control's Text property after parent form Dispose()'d?

Tags:

Long-time joelonsoftware follower, 1st-time stackoverflow poster.

I want to know "how safely" I can do the following (C#):

Form formDlg = new Form();
TextBox box = new TextBox();
formDlg.Controls.Add( box );
formDlg.ShowDialog();
formDlg.Dispose();
string sUserEntered = box.Text; // After parent Dispose'd!

In practice, this (apparently) works, because box (as a Control) has a private text field (a string) which it uses to implement its Text property after its window handle is destroyed.

I won't be satisfied by a general answer that "you can't access an object after it's Disposed" because (1) I can't find any such blanket prohibition in MS docs, (2) I'm not accessing an unmanaged resource, and (3) this code doesn't throw any exception (including ObjectDisposedException).

I would like to do this so I can create and use a combined "ShowAndDispose" method to reduce the risk of forgetting to always call Dispose() after ShowDialog().

To complicate, the behavior changes in the debugger. If I break before Dispose(); then Quick Watch box and drill down into its Control base class; then step past Dispose(); then box.Text returns ""! In other scenarios box.Text returns the user-entered text.

like image 528
Conrad Albrecht Avatar asked Mar 06 '10 16:03

Conrad Albrecht


2 Answers

It is an implementation detail that this code runs without a problem. The Control.Text property happens to be cached by the Control class so disposing the TextBox doesn't cause an ObjectDisposed exception.

That's fairly rare btw, lots of control property getters and setters generate a Windows message to ask the native Window control for the property value. You'll get a kaboom on those because the Handle property is no longer valid. Notable also is that the Text property setter updates the cached value but also generates a Window message to update the native control. Kaboom here.

I assume this is just general interest, don't ever use code like that in your program. Well, you'd find out quick enough.

like image 95
Hans Passant Avatar answered Sep 28 '22 18:09

Hans Passant


You can use the 'using' statement to ensure an object gets disposed when you're done with it:

using(Form frmDialog = new Form())
{
    //Do stuff
}

frmDialog will get disposed once the block has run I believe.

like image 35
RSlaughter Avatar answered Sep 28 '22 18:09

RSlaughter