是否所有注册事件的对象都是IDisposable

时间:2015-06-18 14:27:21

标签: c# events event-handling destructor idisposable

根据我的理解,当不再需要Object时,最好在订阅事件的任何对象中取消订阅所有事件处理程序。

这样做是为了避免在给定Object可能处于无效状态时处理Object中的事件(毫无疑问,我可能不知道其他原因)。

鉴于上述情况,我发现自己在所有注册任何形式的事件处理程序的对象上实现了IDisposible。但是,这会产生明显的复杂性,即必须在给定对象上显式调用Dispose()

最后,我发现自己不确定是否需要这种额外的复杂性,或者我是否应该简单地在对象析构函数中执行事件取消订阅。然而,鉴于对象破坏是非确定性的,这显然会留下意外行为的可能性。

那么注册活动的所有对象都应该是IDisposable吗?或者是否有更适合的替代方法?

2 个答案:

答案 0 :(得分:1)

我建议如果一个对象订阅来自外部对象的通知,无论这些对象是使用事件,IObservable还是其他订阅方式,处置该对象应该确保这些订阅被取消;最自然的方法是使用外部对象支持的常规取消方式。

我进一步建议,如果一个对象接受来自外部对象的订阅请求,它应该销毁对这些对象的引用,如果/很明显不会再向这些订阅者发送通知。通常,一旦某个对象发送了Dispose本身所需的任何通知,它就不会发送任何进一步的通知,因此应该销毁其订阅列表,除非它的语义要求它们超出该范围。

虽然.NET事件模式不能方便地确保订阅被取消,但是从共享对象取消订阅的失败通常会导致代码通常"通常"工作,但将有一些难以验证的要求。如果创建并保留了少量对象,或者创建了无限数量并且所有对象都被放弃,则对象之间的相互引用不会导致内存泄漏,因为在前一种情况下,即使对象需要保留,也需要保留对象。相互引用并不存在,在后一种情况下,尽管相互参照,它们仍将不复存在。然而,创建无限数量的对象并且放弃所有但是少数的情况可能是灾难性的。即使很多物品也是如此。消费者自然会遵守一种或另一种使用模式,要求所有人都必须遵守一种或另一种,而不指定哪种模式是可接受的,这是相当尴尬的。

答案 1 :(得分:0)

你是正确的,事件应该取消订阅,因为如果你不这样做也可能导致内存泄漏。

我不确定是否有建议的或标准的方法,但如果某个类需要清除,那么它通常会实现IDisposable。

另一种选择是记住'取消订阅正确的地方 - 至少IDisposable使这一点更加明显,对于以后访问您的代码的人来说尤其重要。