事件处理程序是否阻止垃圾收集的发生?

如果我有以下代码:

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

pClass会被垃圾回收吗?或者,它是否会在事件发生时仍然徘徊不前?我是否需要执行以下操作才能允许垃圾收集?

MyClass pClass = new MyClass();
pClass.MyEvent += MyFunction;
pClass.MyEvent -= MyFunction;
pClass = null;
32074 次浏览

For the specific question "Will pClass be garbage collected": the event subscription has no effect on the collection of pClass (as the publisher).

For GC in general (in particular, the target): it depends whether MyFunction is static or instance-based.

A delegate (such as an event subscription) to an instance method includes a reference to the instance. So yes, an event subscription will prevent GC. However, as soon as the object publishing the event (pClass above) is eligible for collection, this ceases to be a problem.

Note that this is one-way; i.e. if we have:

publisher.SomeEvent += target.SomeHandler;

then "publisher" will keep "target" alive, but "target" will not keep "publisher" alive.

So no: if pClass is going to be collected anyway, there is no need to unsubscribe the listeners. However, if pClass was long-lived (longer than the instance with MyFunction), then pClass could keep that instance alive, so it would be necessary to unsubscribe if you want the target to be collected.

Static events, however, for this reason, are very dangerous when used with instance-based handlers.

Yes, pClass will be garbage collected. The event subscription does not imply that any reference exists to pClass.

So no, you will not have to detach the handler in order for pClass to be garbage collected.

The moment a piece of memory is no longer referenced it becomes a candidate for garbage collection. When the instance of your class goes out of scope, it is no longer referenced by your program. It is no longer used and therefore can be safely collected.

If you are not sure wether something will get collected ask yourself the following question: does there still exist a reference to it? The event handlers are referenced by the object instance, not the other way around.

pClass will be garbage collected. However, if the code snippet above is inside another class, the instance of that class might not be cleared if you do not set pClass to null.