在父窗体Dispose()'d后访问控件的Text属性?

时间:2010-03-06 16:31:06

标签: c# .net winforms

长期joelonsoftware粉丝,第一次stackoverflow海报。

我想知道“我有多安全”可以执行以下操作(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!

在实践中,这(显然)有效,因为(作为控件)有一个私人文本字段(字符串)它用于在窗口句柄被销毁后实现其Text属性。

我不会满意一般答案“你在处理后无法访问对象”,因为(1)我在MS文档中找不到任何这样的全面禁止,(2)我不是访问非托管资源,以及(3)此代码不会抛出任何异常(包括ObjectDisposedException)。

我想这样做,所以我可以创建并使用组合的“ShowAndDispose”方法来降低忘记在ShowDialog()之后始终调用Dispose()的风险。

要复杂化,调试器中的行为会发生变化。如果我在Dispose()之前休息;然后快速观察并深入查看其 Control 基类;然后走过Dispose();然后box.Text返回“”!在其他情况下,box.Text返回用户输入的文本。

5 个答案:

答案 0 :(得分:2)

您可以使用'using'语句来确保在完成对象时处置对象:

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

frmDialog将在块运行后被处理掉。我相信。

答案 1 :(得分:2)

这是一个实现细节,这段代码运行没有问题。 Control.Text属性恰好由Control类缓存,因此处理TextBox不会导致ObjectDisposed异常。

这是相当罕见的btw,许多控件属性getter和setter生成一条Windows消息,要求本机Window控件获取属性值。你会得到一个kaboom因为Handle属性不再有效。值得注意的是,Text属性设置器更新缓存的值,但也生成一个Window消息来更新本机控件。 Kaboom在这里。

我认为这只是一般兴趣,不要在你的程序中使用这样的代码。好吧,你会发现它足够快。

答案 2 :(得分:1)

调试器场景让我觉得你做的不可靠,测试它你至少应该试试这个:

formDlg.Dispose();
Application.DoEvents();
GC.Collect();
GC.WaitForPendingFinalizers();   
string sUserEntered = box.Text; // After parent Dispose'd!

答案 3 :(得分:0)

我将sUserEntered值放入公共属性中,以便可以访问它:

    public string UserInput
    {
        get;
        set;
    }

    public frmDialog()
    {
        //
        // The InitializeComponent() call is required for Windows Forms designer support.
        //
        InitializeComponent();

        //
        // TODO: Add constructor code after the InitializeComponent() call.
        //
    }

    void Button1Click(object sender, EventArgs e)
    {
        UserInput = userInput.Text;
        this.Dispose();
    }

然后在我的主题中:

        using (dialog = new frmDialog())
        {
            dialog.ShowDialog();
            stringUserInput.Text = dialog.UserInput;
        };

答案 4 :(得分:0)

它发生在我身上,我可以创造&使用一个Form派生类和一个调用ShowDialog()的BeginShowDialog()方法,以及一个调用Dispose()的EndShowDialog()方法。方法名称中的“开始”将使“结束”调用的需要更加明显。

我怀念C ++在离开范围时对当地人的决定性破坏。