我是否必须取消订阅本地变量的匿名事件处理程序?

Fla*_*bug 11 .net c# events event-handling

如果我有一个看起来像这样的代码:

public void Foo()
{
    Bar bar = new Bar();

    bar.SomeEvent += (sender, e) =>
    {
        //Do something here
    };

    bar.DoSomeOtherThingAndRaiseSomeEvent();
}
Run Code Online (Sandbox Code Playgroud)

bar当方法用完范围时会收集,还是我必须手动取消订阅事件以防止内存泄漏,因为引用SomeEvent

Ada*_*son 18

你的情况很好; 事件订阅者不会阻止收集发布者,但可能发生相反的情况.

例如,

class Foo
{
    public event EventHandler FooEvent;

    void LeakMemory()
    {
        Bar bar = new Bar();

        bar.AttachEvent(this);
    }
}

class Bar
{
    void AttachEvent(Foo foo)
    {
        foo.FooEvent += (sender, e) => { };
    }
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,直到Bar创建的实例LeakMemory才能收集

  • lambda表示的匿名方法将从FooEvent调用列表中删除
  • 可以收集它附加的Foo实例

这是因为事件(它只是普通delegate实例上的一些语法糖)保存在调用它时要调用的委托列表中,而这些委托中的每一个都依次引用它所附加的对象(在这种情况下,实例Bar).

请注意,我们这里只讨论收集资格.仅仅因为它符合条件并没有说明什么时候(甚至,真的,如果)它将被收集,只是它可以.