【问题标题】:c#: does subscribing to an event imply reference to the object [duplicate]c#:订阅事件是否意味着引用对象[重复]
【发布时间】:2012-03-09 05:11:24
【问题描述】:
public class A
{
    public delegate void D();
    public event D E;

    ...
}

class B
{
   void Test()
   {
       A a = new A();
       a.E += () => { ... };

       a = null;
   }
}

Test() 结束或由于事件订阅在某处仍然引用它时,a 是否可以被垃圾回收?

【问题讨论】:

标签: c#


【解决方案1】:

是的,a 可以在您的示例中进行 GC。它也不会造成任何问题。想一想。

Class1 a = new Class1();
Class2 b = new Class2();

a.SomeEvent += b.SomeMethod;

在本例中,a 持有对 b 的引用,但反之则不然。 a.SomeEvent 成员就像 List<delegate>(或接近它)。它包含对所有订阅者的引用,因此可以在需要时调用它们。

所以当 a 需要被 GC 时,它可以。它将与订阅者列表一起被销毁。 b 会快乐地活着,没有任何问题。

但另一种方法不起作用 - 无法收集 b,因为 a 仍然持有对它的引用。如果它被收集,那么a 将获得对某个不存在的地方的引用,并且下一次引发该事件的尝试将会爆炸。

【讨论】:

    【解决方案2】:

    通过订阅对象上的事件,您将保留对该对象的引用。

    您需要取消订阅才能释放参考。

    在您的情况下,一旦 Test 完成执行,a 指向的引用将超出范围并有资格进行垃圾回收 - 订阅事件不会改变这一点。

    Why can .NET not have memory leaks? 上查看我的回答。

    【讨论】:

    • 你的意思不是反过来吗?订阅者具有对订阅者的引用。但是如果订阅者可以被 GC 并且订阅者不能,它将会被 GC。也就是说,在OP给出的例子中,a可以被垃圾回收,没有问题。
    • @Vilx- 这就是我写的。 a 有资格进行垃圾收集意味着它将被垃圾收集。
    • 对不起,我被第一句话弄糊涂了:“通过订阅对象上的事件,您保留了对它的引用。”我反过来理解它(b 订阅 a 并保持对它的引用)。
    • @Vilx- 很公平,这不是我写过的最好的句子。
    猜你喜欢
    • 2023-02-10
    • 2014-08-15
    • 2018-07-25
    • 1970-01-01
    • 2013-02-05
    • 1970-01-01
    • 2015-06-21
    • 2022-09-23
    • 1970-01-01
    相关资源
    最近更新 更多