lambda表达式的生命周期是多少?
这是我的问题:我有一个lambda表达式订阅的button1.Click
事件。我不知道是否需要取消订阅(这是不容易的,因为它是匿名的)?或者我不必,因为它与控件(button1)的生命周期相同?
button1.Click += (s, e) => { /*Do something; */};
答案 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();
很酷的是,你可以为这个动作变量添加各种清理代码。