【发布时间】:2009-08-27 14:44:40
【问题描述】:
在 VS 的设计器中,假设您双击一个按钮,它会生成这个 Click 事件处理程序。
订阅代码在designer.cs 中。
我想知道,在处置表单时,我必须取消订阅该活动吗?
另外,表单中的所有控件都会在表单释放时被释放吗?它实际上是递归调用每个控件的 dispose 吗?
【问题讨论】:
在 VS 的设计器中,假设您双击一个按钮,它会生成这个 Click 事件处理程序。
订阅代码在designer.cs 中。
我想知道,在处置表单时,我必须取消订阅该活动吗?
另外,表单中的所有控件都会在表单释放时被释放吗?它实际上是递归调用每个控件的 dispose 吗?
【问题讨论】:
如果您要挂钩自己的事件,则无需在 Dispose 上取消挂钩事件。
如果您将事件挂钩到另一个对象中,您只需要担心它。这样做的原因是事件挂钩使订阅者的引用保持活动状态。如果你没有解开钩子,那么只要 observable 还活着,你就不会收集垃圾。
当你挂钩自己的事件时,你有一个对自己的引用,这是循环的,因此你不必担心它。
出于这个原因,我开始支持更松散耦合的事件模式。这是 .Net 中内存泄漏的第一名。我更喜欢Event Aggregator 模式(带有weak events)。
【讨论】:
关于“它实际上会递归调用每个控件的 dispose 吗?”的问题,答案是肯定的。
可以通过在控件的 Dispose 方法中放置一个断点来完成一个简单的测试。
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.Controls.Add(new SuperButton());
}
}
public class SuperButton : Button
{
protected override void Dispose(bool disposing)
{
//Place breakpoint on the line below
base.Dispose(disposing);
}
}
【讨论】:
只要事件处理程序代码是表单本身,那么您就不需要取消订阅事件 - 因为表单本身会被破坏,控件不会有悬空事件处理程序
【讨论】: