11

我希望通过匿名委托和 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();
}

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

4

3 回答 3

10

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

通常,当某些东西被丢弃时,它很快就会变成垃圾,这意味着你没有问题。

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

于 2009-01-13T14:58:23.143 回答
1

我认为问题在于您似乎是从将委托分配给对象的事件会阻止它被 GC 的假设出发的。

这作为一个简单的陈述是不正确的。

话虽如此,感知到的问题消失了。

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

这样一个绘图过程将如何设法到达这个对象?

于 2009-01-13T14:51:33.030 回答
0

你不能。

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

这就是它被称为匿名的原因。

您必须在某处保存参考……或使用反射。

于 2009-01-13T15:01:18.580 回答