2012-09-29 20 views
2

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

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

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

您的匿名函数对象将在'button1'对象消失后的某个点自动收集垃圾。 –

回答

4

由于lambda表达式与按钮相关的,它将只要按钮不从memory.for你的问题破坏住

我不知道如果我需要需要取消订阅(这是不容易的,因为它是匿名的,因此不容易 )?

Lambda表达式可以保存到一个EventHandler委托中,它可以让您选择访问lambda并从事件中取消订阅。这里是代码。

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

大概就这个话题在这里Should I unsubscribe from events?

+0

谢谢!我想通过这种方式,我们失去了使用lambda表达式作为事件处理程序的好处。这就是为什么我对lambda表达式的生命时间非常感兴趣。你能提供任何线索吗?谢谢! – Roy

+0

在这种情况下不需要退订。如果您希望只要按钮处于活动状态,就可以将相同的事件处理程序与按钮关联起来,请不要担心。请参阅Jon Skeet在此处链接的其他SO线索中的答案。只有在按钮的生命周期中需要更改与按钮关联的事件处理程序时,您是否必须手动删除事件处理程序。 –

4

为导致委托的一辈子都正常CLR对象最好的解释将任何要引用它来定义。在你的情况下,只有button1持有通过Click的参考。因此,它将在button1的同一时间适用于垃圾回收。除非有特殊的原因(即想要将处理程序更改为另一个处理程序),否则不需要执行任何特殊的“释放”操作。

+0

这听起来令人鼓舞,我当前的解决方案!谢谢,阿列克谢。你能给它提供任何参考吗?真的很感激它! – Roy

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(); 

很酷的事情是,你可以添加各种各样的清理代码本法离子变量。

相关问题