对事件处理程序使用lambda表达式


114

我目前有一个页面,其声明如下:

public partial class MyPage : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        //snip
        MyButton.Click += (o, i) =>
        {
            //snip
        }
    }
}

我最近才从1.1迁移到.NET 3.5,因此我习惯于在Page_Load之外编写事件处理程序。我的问题是;为此使用lambda方法时,应该注意什么性能缺陷或陷阱吗?我更喜欢它,因为它肯定更简洁,但是我不想牺牲性能来使用它。谢谢。

Answers:


117

由于编译器会将您的lambda表达式转换为等效的委托,因此不会影响性能。Lambda表达式仅是一种语言功能,编译器会将其翻译为与您使用的完全相同的代码。

编译器会将您需要的代码转换为如下代码:

public partial class MyPage : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        //snip
        MyButton.Click += new EventHandler(delegate (Object o, EventArgs a) 
        {
            //snip
        });
    }
}

我懂了。那么,将这些处理程序放在Page_Load内部与将它们放在外部相比也没有缺点吗?
克里斯托弗·加西亚

1
通用的约定是在OnInit方法中附加事件处理程序,但是由于Click在页面加载后将引发按钮的事件,因此此示例很好。
Andrew Hare 2010年

8
需要注意的重要一点是,如果不保留对委托的引用,就不能取消订阅该事件。
snarf

3
“完全相同的代码”有点误导;至少在从封闭方法中引用局部变量时,lambda表达式不会转换为方法而是类似闭包对象之类的东西,用于存储局部变量的当前值。
OR Mapper

66

在性能方面,它与命名方法相同。最大的问题是何时执行以下操作:

MyButton.Click -= (o, i) => 
{ 
    //snip 
} 

它可能会尝试删除另一个lambda,而将原来的lambda保留在那里。因此,教训是没问题,除非您还希望能够删除处理程序。


3
“它可能会尝试……”?会吗永远删除在这种情况下正确处理?
OR Mapper 2013年

1
@ORMapper:如果lambda捕获变量,则无法删除正确的处理程序。在其他情况下,则取决于编译器。
加布

真?有趣-因此,如果我注册两个看起来相同的匿名函数(wlog的正文为空),然后我注销(使用-=)另一个也为空的匿名函数,则实际上是不确定的,这两个事件处理程序中的哪个将被删除,或者是否将其中任何一个删除?
OR Mapper

4
@ORMapper:是的。如果编译器具有相同的语义(代码不必相同,但它们必须执行相同的操作),并且可以捕获相同的变量实例(不仅仅是相同的变量,但这些变量的实例相同)。有关所有详细信息,请参见C#规范的7.10.8节(委托相等运算符)。
加布

12
如果您确实想使用lambda但需要删除事件,则可以始终将对象保留在局部变量/字段中,然后将其删除,例如var event = (o, e) => doSomething(); handler += event; doSomethingElse(); handler -= event;
Wai Ha Lee

44
EventHandler handler = (s, e) => MessageBox.Show("Woho");

button.Click += handler;
button.Click -= handler;

1
非常有用的信息,尽管不是主题(问题与性能有关)。
斯特凡纳·古里科

4
由于内存使用会导致性能下降,因此并非完全不合时宜。
弗拉迪乌斯

3
在处理程序本身中删除自身也可能会有所帮助:c# EventHandler handler = null; handler = (s, e) => { MessageBox.Show("Woho"); button.Click -= handler;}
Vladius

2

据我所知,它只是“语法糖”,并编译成与使用委托语法等相同的东西,因此我没有意识到或遇到过任何性能影响。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.