如果该事件是唯一持有引用的事物并且我们需要对对象进行垃圾收集,那么通过 WeakReference 实现事件处理是否是一种好习惯?
作为对此的论据:
人们说,如果您订阅了某些内容,您有责任取消订阅,您应该这样做。
如果该事件是唯一持有引用的事物并且我们需要对对象进行垃圾收集,那么通过 WeakReference 实现事件处理是否是一种好习惯?
作为对此的论据:
人们说,如果您订阅了某些内容,您有责任取消订阅,您应该这样做。
尽可能养成退订事件的习惯是件好事,但有时没有明显的“清理”方法可以做到这一点。我们最近发布了一篇关于这个主题的博客文章;它包括使使用 WeakReference 订阅事件变得容易的方法。
弱委托模式应该存在于 CLR 中。正常事件表现出“在你还活着的时候通知我”语义,而我们经常需要“在我活着的时候通知我”。仅仅在 WeakReference 上有委托是错误的,因为委托也是一个对象,即使接收者还活着并且有传入的引用,委托本身也只会被所述 WeakReference 引用,并且会立即被收集。有关实施示例,请参阅此旧帖子。
弱引用本身,并不能解决问题,因为委托持有引用。在 Prism (www.microsoft.com/compositewpf) 附带的复合应用程序库中,有一个 WeakDelegate 类,您可以从源代码中提取该类。WeakDelegate 基本上使用反射并仅在一段时间内创建一个委托,然后释放它,因此不持有任何指针。在 CAL 中,它由 EventAggregator 类使用,但您可以自由地将其撕掉以供自己使用,因为它在 MS-PL 下。
虽然您的建议解决了一组问题(事件引用管理和内存泄漏预防),但它可能会引发一组新问题。
我可以看到的一个问题是,在事件处理过程中,如果源对象被垃圾收集(因为它只被一个弱引用保存),任何访问源对象的代码都会导致空引用异常。您可以争辩说事件处理程序不应该访问源对象,或者它必须具有强引用,但可以争辩说这可能比您首先尝试解决的问题更糟糕。