Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 访问控件';父窗体Dispose()和#x27之后的文本属性;D_C#_.net_Winforms - Fatal编程技术网

C# 访问控件';父窗体Dispose()和#x27之后的文本属性;D

C# 访问控件';父窗体Dispose()和#x27之后的文本属性;D,c#,.net,winforms,C#,.net,Winforms,长期Joelon软件追随者,第一次stackoverflow海报 我想知道我做以下事情的“安全程度”: 实际上,这(显然)是可行的,因为box(作为控件)有一个私有文本字段(字符串),在其窗口句柄被销毁后,它使用该字段实现其文本属性 我不会满足于一个一般性的回答,即“在对象被释放后您无法访问它”,因为(1)我在MS文档中找不到任何这样的全面禁止,(2)我没有访问非托管资源,(3)此代码没有引发任何异常(包括ObjectDisposedException) 我希望这样做,这样我就可以创建并使用一个

长期Joelon软件追随者,第一次stackoverflow海报

我想知道我做以下事情的“安全程度”:

实际上,这(显然)是可行的,因为box(作为控件)有一个私有文本字段(字符串),在其窗口句柄被销毁后,它使用该字段实现其文本属性

我不会满足于一个一般性的回答,即“在对象被释放后您无法访问它”,因为(1)我在MS文档中找不到任何这样的全面禁止,(2)我没有访问非托管资源,(3)此代码没有引发任何异常(包括ObjectDisposedException)

我希望这样做,这样我就可以创建并使用一个组合的“ShowAndDispose”方法来减少忘记在ShowDialog()之后始终调用Dispose()的风险


更复杂的是,调试器中的行为会发生更改。如果我在处理之前打破;然后快速观察框并深入到其控件基类;然后越过Dispose();然后box.Text返回“”!在其他场景框中。Text返回用户输入的文本。

调试器场景使我认为您所做的不可靠,要测试它,您至少应该尝试以下操作:

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

您可以使用“using”语句确保在处理完对象后将其释放:

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

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

我将
受支持的
值放入公共属性,以便可以访问:

    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;
        };

这是一个实现细节,该代码可以毫无问题地运行。Text属性恰好由控件类缓存,因此处理TextBox不会导致ObjectDisposed异常

这是相当罕见的,顺便说一句,许多控件属性getter和setter会生成一条Windows消息,向本机窗口控件请求属性值。由于句柄属性不再有效,您将在这些上获得一个kaboom。值得注意的是,文本属性设置器更新缓存的值,但也会生成一条窗口消息来更新本机控件。我是卡布姆


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

我突然想到,我可以创建并使用一个表单派生类,它带有一个调用ShowDialog()的BeginShowDialog()方法和一个调用Dispose()的EndShowDialog()方法。方法名称中的“Begin”将使“End”调用的需要更加明显


我怀念C++在离开作用域时对局部变量的决定性破坏。

为什么要在窗体上强制执行Dispose?尤其是当您不访问非托管资源时。让框架/GC来处理它。编辑:我觉得您的情况比上面的代码复杂得多。不仅如此,为什么要访问dispose()表单上的文本框。。。?你为什么要这么做?对我来说没有意义?这就像C语言中的指针一样,你对一个指针进行malloc,用它做一些事情,然后释放它,然后在释放指针后取消对它的引用!Zyphrax:一个窗体包含许多非托管资源,每个控件1个。@Henk:是的,但我认为手动处理该类没有用。他的表单不是类变量(据我所知)。最终,它将丢失任何活动引用,并将由其析构函数Dispose调用自动处理。Zyphrax:对于所有IDisposable对象都是这样,但我们有一次性模式、IDisposable接口和using子句,因为我们应该始终清理自己。GC非常低效且不可预测。这并不能真正改变他的问题。相比之下,
字符串suserented=box.Text会在using块之后出现。是的,这比ShowAndDispose()方法更好。@zyprax,不,它会解决OP忘记Dispose的问题,当然还有这个框。文本代码会在using.Thx中出现,但我认为using很难看,如果我记得使用using,我可以很容易地记住调用Dispose()@Conrad:习惯于使用
,每个人都是这样。你可以免费试用/最终试用。好吧,我试过了,它仍然“有效”。formDlg和box变量仍在作用域中,因此我不希望GC影响它们的对象。反正是Thx。@Conrad:我仍然怀疑,为什么文本会在调试器中消失?我做了一些测试,文本确实消失了,我尝试了所有的变体。在我将控件中的文本值放入公共属性之前,我无法将文本值返回到我的主窗体-请参见下面的答案。Thx,我知道我可以做到这一点,创建一个全新的类需要比我想要的多得多的代码。您仍然需要将其包装在try/finally块中,因此,使用的好处是有争议的。我将跳过try/finally。在ShowDialog()抛出的真实世界中从未发生过的情况下,我将忍受资源泄漏。我不同意“使用”“解决”我想要解决的问题,这一点永远不会忘记,对于我使用的数百个类,何时/是否需要处理每一个类。如果我不记得了,那么我就不会记得对该类使用“using”比调用Dispose()更好。是的,我重用自己代码的方式是,如果我有一个隐藏ShowDialog()的ModalDialog类,那么我想我会使用它。但老实说,在花了这么多时间讨论Dispose()之后,我可能要花很长时间才能再次忘记它
        using (dialog = new frmDialog())
        {
            dialog.ShowDialog();
            stringUserInput.Text = dialog.UserInput;
        };