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)
这是一个好方法吗?这种方法有什么不良副作用吗?
这是一个坏主意,因为:
请参阅链接的答案。这是 95% 的重复,但我认为还不足以结束这个问题。我将引用最相关的部分:
弱引用还会导致语义差异和不确定性。如果您参加() => LaunchMissiles()某些活动,您可能会发现导弹有时会发射。其他时候,GC 已经拿走了处理程序。这可以通过依赖句柄来解决,这会带来另一层复杂性。
我个人认为事件的强引用性很少会成为问题。通常,事件连接在具有相同或非常相似生命周期的对象之间。例如,您可以在 ASP.NET 中的 HTTP 请求上下文中挂钩所有您想要的事件,因为当请求结束时,所有内容都将有资格收集。任何泄漏都有其规模和短暂性。