Lambda 表达式作为事件处理程序

Lambda 表达式可用于处理事件,这在以下情况下非常有用:

  • 处理程序很简短。
  • 处理程序永远不需要取消订阅。

下面给出了一个可能使用 lambda 事件处理程序的好情况:

smtpClient.SendCompleted += (sender, args) => Console.WriteLine("Email sent");

如果需要在代码中的某个未来点取消订阅已注册的事件处理程序,则应将事件处理程序表达式保存到变量,并通过该变量完成注册/取消注册:

EventHandler handler = (sender, args) => Console.WriteLine("Email sent");

smtpClient.SendCompleted += handler;
smtpClient.SendCompleted -= handler;

之所以这样做,而不是简单地重新输入 lambda 表达式,以便取消订阅它(-=),那么 C#编译器不一定会认为这两个表达式是相等的:

EventHandler handlerA = (sender, args) => Console.WriteLine("Email sent");
EventHandler handlerB = (sender, args) => Console.WriteLine("Email sent");
Console.WriteLine(handlerA.Equals(handlerB)); // May return "False"

请注意,如果将其他语句添加到 lambda 表达式,则可能会意外省略所需的周围花括号,而不会导致编译时错误。例如:

smtpClient.SendCompleted += (sender, args) => Console.WriteLine("Email sent"); emailSendButton.Enabled = true;

这将编译,但会导致将 lambda 表达式 (sender, args) => Console.WriteLine("Email sent"); 添加为事件处理程序,并立即执行语句 emailSendButton.Enabled = true;。要解决这个问题,lambda 的内容必须用大括号括起来。这可以通过从一开始就使用花括号来避免,在向 lambda-event-handler 添加其他语句时要小心,或者从开头用圆括号括起 lambda:

smtpClient.SendCompleted += ((sender, args) => Console.WriteLine("Email sent"));
//Adding an extra statement will result in a compile-time error