将lambda表达式用于事件处理程序的最佳实践

时间:2010-07-14 16:14:17

标签: c# events lambda

在发现lambda表达式及其作为匿名函数的用法之后,我发现自己编写了许多更为琐碎的事件,例如:

txtLogin.GotFocus += (o, e) =>
{
    txtLogin.Text = string.Empty;
    txtLogin.ForeColor = SystemColors.ControlText;
};
txtLogin.LostFocus += (o, e) =>
{
    txtLogin.Text = "Login...";
    txtLogin.ForeColor = SystemColors.InactiveCaptionText;
};

我也离开了只调用其他函数的事件处理程序,用同样的小lambda代替它们:

backgroundWorker.DoWork += (o, e) => DatabaseLookup.Open(e.Argument as string);

我发现了一些与performance concerns相关的类似问题并指出你can't remove them,但我还没有找到解决这个简单问题的简单问题吗?

使用lambdas是否被认为是一种良好的形式,或者更多的经验是程序员看不起这个?它是否在难以找到的位置隐藏事件处理程序,还是通过减少简单事件处理程序的数量来使代码成为服务?

3 个答案:

答案 0 :(得分:15)

这是一个非常合理的想法 - 但在这种特殊情况下,我会使用匿名方法代替:

txtLogin.LostFocus += delegate
{
    txtLogin.Text = "Login...";
    txtLogin.ForeColor = SystemColors.InactiveCaptionText;
};

好处是您不必指定参数 - 这使您更清楚地知道不使用它们。这是匿名方法对lambda表达式的唯一优势。

性能打击几乎总是可以忽略不计。如果你需要能够删除处理程序,那么之后无法删除它们是一个非常现实的问题,但我发现通常我不这样做。 (Reactive Extensions对此有一个很好的方法 - 当你订阅一个可观察的序列时,你会得到一个IDisposable,如果你调用它,它将删除订阅。非常整洁。)

答案 1 :(得分:1)

实际上,它认为它将事件处理程序放在易于查找的位置,即紧挨着它所分配的事件的名称。

很多时候,你会看到像:

这样的事件处理程序
 void Text1_KeyDown(....) {....}

附加到txtFirstName的KeyUp事件,因为在使用Intellisense创建处理程序后,有人决定重命名文本框,并且KeyUp工作得更好。使用Lambda,对象,事件和功能都在一起。

答案 2 :(得分:0)

这是一个棘手的问题。我记得在Code Complete中读到一些(智能)人如何说你应该尽可能简化控制流程,许多人争论单一进入和退出点来自一种方法,因为不这样做会使程序更难跟随。

Lambdas距离更远,在某些情况下很难跟踪正在发生的事情,控制权从一个地方跳到另一个地方。

基本上,我认为这可能是一个坏主意,但它也很强大,让生活更轻松。我当然使用它们相当数量。总之,请谨慎使用!