lambda表达式的生命范围是什么?

时间:2012-09-29 04:01:56

标签: c# lambda

lambda表达式的生命周期是多少?

这是我的问题:我有一个lambda表达式订阅的button1.Click事件。我不知道是否需要取消订阅(这是不容易的,因为它是匿名的)?或者我不必,因为它与控件(button1)的生命周期相同?

button1.Click += (s, e) => { /*Do something; */};

3 个答案:

答案 0 :(得分:4)

由于lambda表达式与按钮相关联,只要按钮没有从内存中销毁,它就会存在。对于你的问题

  

我不知道是否需要取消订阅(这并不容易   因为它是匿名的)?

Lambda表达式可以保存到EventHandler委托中,它为您提供了访问lambda和取消订阅事件的选项。这是代码。

    EventHandler myEvent= (s, e) => { /*Do something; */};  
    //Subscribe
    button1.Click += myEvent;
    //Unsubscribe
    button1.Click -= myEvent;

这里可能是关于这个主题的最佳解释Should I unsubscribe from events?

答案 1 :(得分:4)

因为所有正常的CLR对象导致委托的生命周期将由引用它的任何内容定义。在您的情况下,只有button1通过Click保留引用。因此,它将在button1的同时可用于垃圾收集。除非有特殊原因(即想要将处理程序改为另一个),否则你不需要做任何特别的事情来“释放”它。

答案 2 :(得分:2)

通过使用局部变量捕获事件处理程序,可以轻松保留对事件处理程序引用的引用。

        EventHandler click = (s, e) => { /* Do something; */ };

然后你可以这样附上它:

        this.button1.Click += click;

清理可能会有点棘手,因为它通常需要您创建一个类级变量来保存对处理程序的引用。这导致代码分散在整个班级中。

然而,有一种相当简单的方法来处理它。进行类级别cleanup操作以捕获所有清理操作,如下所示:

        private Action cleanup = () => { };

现在,附加事件处理程序的代码可以很好地定位在单个方法中,如下所示:

        EventHandler click = (s, e) => { /* Do something; */ };
        this.button1.Click += click;
        cleanup += () => this.button1.Click -= click;

完成表单后,您可以像这样快速清理:

        cleanup();

很酷的是,你可以为这个动作变量添加各种清理代码。