EventHandlers和匿名委托/ Lambda表达式

时间:2009-01-13 14:44:11

标签: c# events delegates lambda anonymous-methods

我希望用匿名委托和lambda表达式来清除一些事情,用于为C#中的事件处理程序创建一个方法,至少对我自己来说。

假设我们有一个添加匿名委托或lambda表达式的事件(对于可以使用较新版本.NET的幸运人群)。

SomeClass.SomeEvent += delegate(object o, EventArg e) { /* do something */ };

我读过,过去的人们已经忘记了仍然有处理程序的事件,这些处理程序会阻止类被垃圾收集。如何在不在类中将SomeEvent设置为null的情况下删除添加的处理程序。以下不是一个全新的处理程序吗?

SomeClass.SomeEvent -= delegate(object o, EventArg e) { /* do something */ };

我可以看到将匿名委托或lambda表达式存储在变量中。但至少对我而言,这似乎打败了能够简单而简洁地添加事件处理程序的全部目的。

SomeEventDelegate handler = new SomeEventDelegate(delegate(object o, EventArg e) { /* do something */ });
SomeClass.SomeEvent += handler;
// ... stuff
SomeClass.SomeEvent -= handler;

同样,我明白你可以做......

public override Dispose(bool disposing)
{
    _someEvent = null;
    this.Dispose();
}

但是我只是从事件中删除动态创建的方法更有趣。希望有人可以为我揭开这一点。谢谢!

3 个答案:

答案 0 :(得分:10)

如果对象X有一个事件处理程序,其目标是对象Y,则对象X处于活动状态意味着对象Y不能被垃圾回收。它不会阻止对象X被垃圾收集。

通常情况下,当处理某些东西时,它很快就会变成垃圾,这意味着你没有问题。

事件和GC的问题在于,如果您忘记从不同的对象中删除已订阅的处理程序 - 即您有一个已处置的侦听器,但永远不会被垃圾收集,因为仍有引用来自不同对象的事件。

答案 1 :(得分:1)

我认为问题在于你似乎是在假设将一个委托分配给一个对象的事件来阻止它被GC化。

这只是一个简单的陈述。

据说这个问题消失了。

最初在垃圾收集中,一切都是垃圾。 GC运行全局和每个堆栈上当前可用的所有东西,以及它们引用的其他对象等等,将每个对象标记为非垃圾。

这样的图表处理如何设法达到这个目标?

答案 2 :(得分:0)

你不能。

就像你不能在其范围之外创建匿名类型(除了一些编译器技巧)。

这就是为什么它被称为匿名。

您必须在某处保存引用...或使用反射。