c# - 我必须在终结器中删除 eventHandlers 吗?

标签 c# wpf

我有一个模型类,它有一个 Saved 事件。这个想法是,如果两个 View 模型使用该模型对象,如果其中一个更改它,另一个将被更新。

当我不再使用它的 View 模型时,是否必须删除事件处理程序?这是我的代码:

protected AbstractEntityViewModel(AbstractEntity ae)
{
    this.ae = ae;

    ae.Saved += delegate(object o, EventArgs e) 
    { 
        base.OnPropertyChanged(null);
    };
}

这样可以吗,还是我需要更改它以便在不再使用 View 模型时-= 摆脱委托(delegate)?

最佳答案

事件引用方向

要知道您是否真的需要分离事件处理程序,您首先必须了解:

ae.Saved += delegate(object o, EventArgs e) 
{ 
    base.OnPropertyChanged(null);
};

表示 ae 现在正在引用 this。因此,具有事件的对象正在引用具有事件处理程序的对象。不是相反(事件处理程序引用事件)。

没有被GC root引用的对象可以被回收

此外,虽然理想情况下要进行垃圾回收的对象不会被任何其他对象引用,但这并不是绝对必要的:

垃圾收集器可以收集所有未被 GC 根以任何方式(路径)引用的对象。这意味着如果你有一个孤立的对象图(对象引用图中的其他对象,但图外没有对象引用图中的对象[也没有 GC 根]),那么整个对象图最终会被垃圾收集。图越交织,GC 收集它的成本就越高。分离事件处理程序有助于更快速地分解此类图。

正确清理对象

.Net 没有析构函数。取而代之的是 IDisposable 模式和终结器(参见 Implementing Finalize and Dispose to Clean Up Unmanaged Resources )。

长话短说:

  • 当对象管理非托管资源时,需要完成方法(~Foo () { } for class Foo)。当 GC 收集对象时,垃圾收集器会调用它们。所以确切的时间不取决于你。
  • 一次性模式可用于清理托管和非托管资源。如果对象有非托管资源,它仍然必须有一个终结器。为什么? Dispose() 方法由您调用。不能保证它会被执行。如果应用程序未能调用 Dispose() 方法,则仍然存在调用 finalize 的 GC。因此,基本上在 Dispose 中进行非托管资源清理只是一种性能改进(在某些情况下,这可能非常重要,除非您想在计算机中插入更多 GB 的 RAM...)。

如果您打算使用终结器,我强烈建议您阅读有关它的文档,因为有很多东西我没有在这里介绍。参见 Implementing Finalize and Dispose to Clean Up Unmanaged Resources

你的例子

回到你的例子,在你构造一个 AbstractEntityViewModel 之后,只要你传递给 AbstractEntityViewModel< 的 AbstractEntity 它就会一直存在 保持事件状态,反之亦然。 但是当这两者都没有被 GC 根引用时,它们都会被垃圾收集。

如果您分离事件处理程序,即使 AbstractEntity 不能,AbstractEntityViewModel(或者更确切地说,它是具体的子类实例)也可以被垃圾回收。

另见:Understanding Garbage Collection in .NET


关于c# - 我必须在终结器中删除 eventHandlers 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10177455/

相关文章:

c# - 将 List<Object> 绑定(bind)到 c# wpf 中的组合框

c# - 调用相同方法的不同对象,如何设置 "caller' s"属性?

c# .NET 在保持相同 session 的同时加载/卸载程序集

c# - 如何比较两个可执行文件?

c# - 为什么我在 SignalR 上收不到以复杂对象作为参数的事件?

wpf - 创建可滚动的 WPF 用户控件

JavaScript 代码在 WPF WebBrowser 加载的 HTML 页面中不起作用

c# - WPF 中的可拖动 Canvas 使用 'Thumb'

javascript - 仅从 HighCharts 禁用打印图表选项

c# - WPF 应用程序性能