C# 是否需要处置以取消事件注册?

C# 是否需要处置以取消事件注册?,c#,.net,events,dispose,C#,.net,Events,Dispose,假设我有两个类,它们都不是GUI组件。类A是一个短期对象,它注册由长期对象B声明的事件 public A(B b) { b.ChangeEvent += OnChangeEvent; } 如果A从未注销B的事件,A将永远不会被垃圾收集吗?A是否需要一个Dispose方法来注销B的事件 还有一个相关的第二个问题。如果A和B都应该在应用程序的整个执行时间内都有效,A是否需要取消注册?如果B持有对A的引用,A将不会获得垃圾收集,除非B也有资格进行垃圾收集 您不应该为此需要Dispose方法。一

假设我有两个类,它们都不是GUI组件。类A是一个短期对象,它注册由长期对象B声明的事件

public A(B b)
{
   b.ChangeEvent += OnChangeEvent;
}
如果A从未注销B的事件,A将永远不会被垃圾收集吗?A是否需要一个Dispose方法来注销B的事件


还有一个相关的第二个问题。如果A和B都应该在应用程序的整个执行时间内都有效,A是否需要取消注册?

如果B持有对A的引用,A将不会获得垃圾收集,除非B也有资格进行垃圾收集

您不应该为此需要Dispose方法。一旦B也没有指向它的引用,垃圾收集器将足够聪明来处理B和A


如果它们在应用程序的生命周期内都处于活动状态,则无需取消注册该事件。

对于第一个问题:是。B引用了a。这样a将和B一样长寿。如果你注册了app.OnIdle之类的事件,这是一种释放UI应用程序内存的好方法


到第二个:最后所有的东西都将被杀死。

正如您所怀疑的,断开事件连接的正确位置将位于
IDisposable.Dispose
方法
A
。没有什么好的选择。尝试在
A
的终结器/析构函数中断开事件的连接是没有用的,因为
A
在断开与
B
的连接之前唯一有资格进行垃圾收集的方法是
B
自身有资格进行垃圾收集;一旦发生这种情况,订阅将成为一个没有意义的点,因此无论它是否被清理


如果有必要在长寿命发布者的生命周期内清理来自废弃的短命订阅者的事件,那么如果发布类和订阅类相互合作,就可以这样做。例如,事件订阅者的公共面可以是一个包装器对象,它持有对实际事件订阅者的引用,而订阅者本身并不持有对该公共对象的强引用。在这种情况下,事件订阅不会阻止公共对象脱离范围并有资格最终确定。公共对象中的终结器可以通知订阅对象不再需要订阅,并且应该取消订阅。由于此类通知将异步到达,发布订阅的对象必须提供一种方式,通过该方式订阅方可以异步取消订阅。这可以通过正常的“取消订阅”请求来完成,前提是发布事件保证它是非阻塞和线程安全的;不幸的是,大多数活动都没有这样的保证。

。。。除非A也有资格进行垃圾收集。@Sean,我有B和A。一旦从B中删除外部引用,A也将被处理。如果在
B
的生存期内可能创建的
A
的数量没有限制,则未能断开事件将表示无限内存泄漏。如果
A
在其有效生存期内需要
B
发布事件,则
A
应在其Dispose方法中实现
IDisposable
并断开事件与
B
的连接。