在以下课程中:
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个控件),而第二种方式工作正常。如果我能愉快地使用第二个,那就太棒了。
答案 0 :(得分:3)
是的,处理容器会自动处理其子控件。
根据MSDN documentation,Control.Dispose
方法:
释放Control 及其子控件使用的非托管资源,并可选择释放托管资源。
因此调用Dispose
控件上的Panel
方法将自动释放其子控件。但是,正如Joe的评论所指出的那样,有一个重要的警告:子控件必须取消订阅在父级范围之外声明的事件。如果事件是将保持活动的对象的成员,它们将使子控件保持活动状态并防止它们被正确处理。显然,您不需要取消订阅同时处理的对象中声明的事件,例如父级。
当然,这也可以扩展到Panel
控件的容器(很可能是Form
控件)。只要您Dispose
拥有Form
的{{1}},Panel
控件及其所有子项都将自动为您处理。没有理由明确地为Panel
控件执行此操作,除非您动态地在表单中添加和删除实例。
答案 1 :(得分:2)
这两个不完全相同,你可以通过使用Reflector查看Control.Dispose
的实现来轻松看到(当它仍然是免费的时很容易做到!)
例如,如果您只是在面板上调用Dispose,它将在每个子控件上调用DisposeAxControls,并在调用其子项上的Dispose之前将其自身从其父控件中删除。
尽管如此,我同意Cody Gray的看法 - 你需要弄清楚为什么它会冻结,而不是试图用你提议的解决方法“解决地毯下的问题”。
通常情况下,您不会明确地调用Panel上的Dispose - 如果您这样做,则需要确保正确管理控件的生命周期和所有权。
要做的是逐步开始简化你的应用程序直到它不再冻结 - 找出导致冻结的原因(例如,通过删除你逐一提到的计时器 - 这听起来很可疑)。一旦你有一个展示问题的非常简单的例子,你(或这里的某个人)将更容易弄清楚正在发生的事情。