在引擎盖下引用弱引用的C#事件是一个好主意吗?

Lea*_*yes 11 .net c# events weak-references

我一直想知道是否值得使用类似下面的内容(粗略的概念证明代码)来实现弱事件(它们是合适的):

class Foo {

    private WeakEvent<EventArgs> _explodedEvent = new WeakEvent<EventArgs>();

    public event WeakEvent<EventArgs>.EventHandler Exploded {
        add { _explodedEvent += value; }
        remove { _explodedEvent -= value; }
    }

    private void OnExploded() {
        _explodedEvent.Invoke(this, EventArgs.Empty);
    }

    public void Explode() {
        OnExploded();
    }

}
Run Code Online (Sandbox Code Playgroud)

允许其他类使用更常规的C#语法订阅和取消订阅事件,同时实际上使用弱引用实现:

static void Main(string[] args) {
    var foo = new Foo();
    foo.Exploded += (sender, e) => Console.WriteLine("Exploded!");

    foo.Explode();
    foo.Explode();
    foo.Explode();

    Console.ReadKey();
}
Run Code Online (Sandbox Code Playgroud)

WeakEvent<TEventArgs>辅助类的定义如下:

public class WeakEvent<TEventArgs> where TEventArgs : EventArgs {

    public delegate void EventHandler(object sender, TEventArgs e);

    private List<WeakReference> _handlers = new List<WeakReference>();

    public void Invoke(object sender, TEventArgs e) {
        foreach (var handler in _handlers)
            ((EventHandler)handler.Target).Invoke(sender, e);
    }

    public static WeakEvent<TEventArgs> operator + (WeakEvent<TEventArgs> e, EventHandler handler) {
        e._handlers.Add(new WeakReference(handler));
        return e;
    }

    public static WeakEvent<TEventArgs> operator - (WeakEvent<TEventArgs> e, EventHandler handler) {
        e._handlers.RemoveAll(x => (EventHandler)x.Target == handler);
        return e;
    }

}
Run Code Online (Sandbox Code Playgroud)

这是一个好方法吗?这种方法有什么不良副作用吗?

usr*_*usr 3

这是一个坏主意,因为:

  1. 您的程序开始变得不确定,因为副作用取决于 GC 的操作。
  2. GCHandle 的代价是性能。

请参阅链接的答案。这是 95% 的重复,但我认为还不足以结束这个问题。我将引用最相关的部分:


弱引用还会导致语义差异不确定性。如果您参加() => LaunchMissiles()某些活动,您可能会发现导弹有时会发射。其他时候,GC 已经拿走了处理程序。这可以通过依赖句柄来解决,这会带来另一层复杂性。

我个人认为事件的强引用性很少会成为问题。通常,事件连接在具有相同或非常相似生命周期的对象之间。例如,您可以在 ASP.NET 中的 HTTP 请求上下文中挂钩所有您想要的事件,因为当请求结束时,所有内容都将有资格收集。任何泄漏都有其规模和短暂性。