写内联事件处理程序是一种不好的做法吗?

74

编写内联事件处理程序是不好的实践吗?

对我来说,当我想在事件处理程序中使用局部变量时,我更喜欢使用它,如下所示:

我更喜欢这样做:

// This is just a sample
private void Foo()
{
    Timer timer = new Timer() { Interval = 1000 };
    int counter = 0; // counter has just this mission
    timer.Tick += (s, e) => myTextBox.Text = (counter++).ToString();
    timer.Start();
}

不要这样做:

int counter = 0; // No need for this out of Boo & the event handler

private void Boo()
{
    Timer timer = new Timer() { Interval = 1000 };

    timer.Tick += timer_Tick;
    timer.Start();
}

void timer_Tick(object sender, EventArgs e)
{
    myTextBox.Text = (counter++).ToString();
}

1
是的,lambda表达式和闭包确实很邪恶... - user395760
6
我认为这取决于你的团队。如果每个人都熟悉这些功能,那么就没问题。我个人喜欢将lambda表达式放在单独的一行中更加明显,等等。我喜欢编写代码,使一行代码只做一件事情。 - kenny
+1 @kenny 我同意你的观点,这会使代码更易读。 - Omar
同意 Kenny 的观点。一旦您接受了 Jon 的答案并确定从技术角度来看它是好的(性能、可扩展性等),好/坏的实践都在于预测谁将阅读或修改此代码以及他们将如何感知它,包括在您忘记它的功能后的自己。 - xr280xr
3个回答

87

这完全没问题——不过有两个注意点:

  • 如果你从闭包内修改局部变量,你应该确保自己明白自己在做什么。
  • 你将无法取消对事件的订阅。

通常情况下,我只在内联非常简单的事件处理程序时使用lambda表达式(或匿名方法)进行订阅,并调用一个更适合的方法:

// We don't care about the arguments here; SaveDocument shouldn't need parameters
saveButton.Click += delegate { SaveDocument(); };

3
这个答案可能会导致人们走上错误的道路。视情况而定,事件处理程序是否可以取消订阅的重要性不同。在内存受限的情况下(例如移动设备),清理事件处理程序以确保ViewControllers和Activities能够被正确地垃圾回收非常重要。如果未能这样做,可能会导致显著的内存分配增加,或者当事件触发时,屏幕在导航返回堆栈中而当前未显示时产生意想不到的行为。根据您的用例,了解是否可以不解除事件绑定很重要。 - SmartyP
4
@SmartyP:用户应该知道他们是否需要取消订阅事件——在我看来,这并不是这个问题的范围。我已经明确表示他们无法这样做,这意味着如果他们需要这样做,他们将知道不要使用匿名函数。 - Jon Skeet
保留委托的引用以便稍后删除。https://dev59.com/CHM_5IYBdhLWcg3wgzdl#2915741 - Ian

3
在大多数情况下,我更喜欢像“timer_Tick()”这样的单独方法,但是我更喜欢将其称为OnTimerTick(),因为:
  • 当我阅读类时,更清楚正在发生什么。 “On”告诉我它是一个事件处理程序。
  • 在“inline”情况下,在方法中设置断点更容易。
  • 事件在“Foo”构造函数返回很长时间后触发,我认为它不会在构造函数的范围内运行。

但是,如果事件只会在声明它的方法返回之前触发,并且设置事件的对象的作用域仅限于声明方法,则我认为“in line”版本更好。因此,我喜欢使用“in line”来比较传递给“sort”方法的委托。


-1

你把这两个示例放在一起。很明显第二个选项(虽然你不喜欢)是最易读的。

代码的可读性和可维护性非常重要。保持简单,尽可能易于理解。Lambda表达式通常被大多数人认为更难理解。即使它们对你来说已经是第二天性,但对其他人来说可能不是。


3
就我个人而言,我发现Lambda语法更容易在头脑中分析,并且更喜欢第一个示例。但这是4年后的情况。 - Holf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接