是否处置相当于处置其子女加上自己的面板?

时间:2011-02-04 04:18:53

标签: c# .net winforms controls dispose

在以下课程中:

class MyPanel : Panel
{
    ...
    protected override void Dispose(bool disposing)
    {
        // My code here
    }
}

以下两个代码示例是等效的吗?

base.Dispose(disposing);

VS

if (disposing)
{
    List<Control> ctrls = new List<Control>(this.Controls);
    this.Controls.Clear();  
    foreach(Control c in ctrls)
    {
         c.Dispose();
    }
}
base.Dispose(disposing);

如果它们有不同的效果,它会是什么?

编辑我问这是因为,无论出于何种原因,这样做是第一种方式冻结我的程序,然后才能处理它的任何子项(disposing为真,{{{ 1}}包含2个控件),而第二种方式工作正常。如果我能愉快地使用第二个,那就太棒了。

2 个答案:

答案 0 :(得分:3)

是的,处理容器会自动处理其子控件。

根据MSDN documentationControl.Dispose方法:

  

释放Control 及其子控件使用的非托管资源,并可选择释放托管资源。

因此调用Dispose控件上的Panel方法将自动释放其子控件。但是,正如Joe的评论所指出的那样,有一个重要的警告:子控件必须取消订阅在父级范围之外声明的事件。如果事件是将保持活动的对象的成员,它们将使子控件保持活动状态并防止它们被正确处理。显然,您不需要取消订阅同时处理的对象中声明的事件,例如父级。

当然,这也可以扩展到Panel控件的容器(很可能是Form控件)。只要您Dispose拥有Form的{​​{1}},Panel控件及其所有子项都将自动为您处理。没有理由明确地为Panel控件执行此操作,除非您动态地在表单中添加和删除实例。

答案 1 :(得分:2)

这两个不完全相同,你可以通过使用Reflector查看Control.Dispose的实现来轻松看到(当它仍然是免费的时很容易做到!)

例如,如果您只是在面板上调用Dispose,它将在每个子控件上调用DisposeAxControls,并在调用其子项上的Dispose之前将其自身从其父控件中删除。

尽管如此,我同意Cody Gray的看法 - 你需要弄清楚为什么它会冻结,而不是试图用你提议的解决方法“解决地毯下的问题”。

通常情况下,您不会明确地调用Panel上的Dispose - 如果您这样做,则需要确保正确管理控件的生命周期和所有权。

要做的是逐步开始简化你的应用程序直到它不再冻结 - 找出导致冻结的原因(例如,通过删除你逐一提到的计时器 - 这听起来很可疑)。一旦你有一个展示问题的非常简单的例子,你(或这里的某个人)将更容易弄清楚正在发生的事情。