193

如果我有以下代码:

MyClass pClass = new MyClass();
pClass.MyEvent += MyFunction;
pClass = null;

pClass 会被垃圾回收吗?或者它是否会在事件发生时仍然触发它的事件?为了允许垃圾收集,我需要执行以下操作吗?

MyClass pClass = new MyClass();
pClass.MyEvent += MyFunction;
pClass.MyEvent -= MyFunction;
pClass = null;
4

4 回答 4

226

对于具体问题“PClass 是否会被垃圾回收”:事件订阅对 pClass 的收集没有影响(作为发布者)。

对于一般的 GC(特别是目标):这取决于 MyFunction 是静态的还是基于实例的。

实例方法的委托(例如事件订阅)包括对实例的引用。所以是的,事件订阅将阻止 GC。但是,一旦发布事件的对象(上面的 pClass)符合收集条件,这将不再是问题。

请注意,这是单向的;即如果我们有:

publisher.SomeEvent += target.SomeHandler;

那么“发布者”将使“目标”保持活动状态,但“目标”不会让“发布者”保持活动状态。

所以不:如果无论如何都要收集 pClass,则无需取消订阅侦听器。但是,如果 pClass 是长期存在的(比具有 MyFunction 的实例长),那么 pClass 可以使该实例保持活动状态,因此如果您希望收集目标,必须取消订阅。

然而,由于这个原因,静态事件在与基于实例的处理程序一起使用时非常危险。

于 2008-11-18T09:43:27.147 回答
9

是的,pClass将被垃圾收集。事件订阅并不意味着存在对 的任何引用pClass

所以不,您不必为了pClass垃圾收集而分离处理程序。

于 2008-11-18T09:49:23.563 回答
8

当一块内存不再被引用时,它就成为垃圾回收的候选对象。当您的类的实例超出范围时,您的程序将不再引用它。它不再使用,因此可以安全地收集。

如果您不确定是否会收集某些东西,请问自己以下问题:是否仍然存在对它的引用?事件处理程序由对象实例引用,而不是相反。

于 2008-11-18T10:55:37.097 回答
0

pClass将被垃圾收集。但是,如果上面的代码片段在另一个类中,如果您不设置pClass为,则该类的实例可能不会被清除null

于 2012-06-07T13:31:51.600 回答