长期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返回用户输入的文本。
答案 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 ++在离开范围时对当地人的决定性破坏。