2

我有一个这样声明的按钮事件:

myButton.Click += new EventHandler(ButtonClicked);

private void ButtonClicked(Object s, EventArgs e)
{
  this.Close();
}

我可以这样做:

myButton.Click += (s, e) => this.Close();

我确信使用第二种方式的好处不仅仅是美观。

为什么以及何时应该使用第二种方法,因为现在我很困惑?如果只是为了外观,当您在匿名函数的主体中有多个指令时,它看起来并不会更干净。

4

8 回答 8

4

从技术上讲没有区别。编译器将在第二种情况下生成处理程序方法。

但坦率地说,我几乎从不使用匿名事件处理程序。为什么?因为他们没有名字。IDE 无法帮助我找到处理事件的地方。您还记得您使用匿名方法订阅的确切位置吗?嗯,你可能还记得那个地方。但我敢打赌你的队友不会。

我也不喜欢混合事件处理程序的风格。Visual Studio 为我生成button1_Click方法。我不喜欢一些处理程序以这种方式订阅,而一些处理程序就地订阅。

而且我喜欢查看事件参数类型。是的,退订有时也很重要。还有几点-匿名方法对于非常简单的逻辑很有用(例如在您的情况下关闭表单),但是对于更复杂的事情它们会变得非常混乱。而且我认为将事件处理程序放在适当的位置会破坏您方法的单一职责。它订阅事件,做一些其他的事情,并在同一个地方处理事件。我喜欢将事物分开以使它们更具可读性和可维护性。

于 2013-02-20T14:16:54.503 回答
2

(s, e) => this.Close();无论哪种方式,编译器都会为这个匿名函数生成一个方法,

这取决于您想在哪里使用它,在方法中声明它可以让您访问在该方法中声明的变量。

于 2013-02-20T14:02:44.547 回答
1

好吧,您基本上已经隐含地将委托应用于您的Click活动。

您无法在其他任何地方的代码中访问此事件。这样做的主要优点是,您不能在类中的任何其他位置调用您的方法,通过拥有一个方法,您可以邀请其他“团队成员”在他们的代码中访问该方法,或者可能将它的修饰符更改为他们的认为应该发生。

如果您希望能够使用override一种方法,那么显然内联匿名分配是不利的。

用法或多或少取决于您希望如何处理对逻辑的访问。

于 2013-02-20T14:04:51.457 回答
1

如果你不需要参数,你可以做得更优雅:

myButton.Click += delegate { this.Close(); };

但它背后除了优雅的外观没有任何利润。

如果我真的不需要它们,我不喜欢使用 lambda 表达式 ( => ),因为您无法在调试期间更改范围代码。

于 2013-02-20T14:08:16.820 回答
1

匿名函数可以是匿名方法或 lambda 表达式。Lamba 表达式的形式为:

() => //dowork

匿名方法更加冗长,并且支持主要是为了向后兼容。匿名函数本身没有值或类型,但它可以转换为委托或表达式树。匿名函数允许我们创建内联方法,这些方法在设置事件处理程序等情况下很有用。这种方法的内联允许开发人员“在同一个地方”编写代码。换句话说,处理程序在处理事件的位置立即可供阅读器使用。

当实现仅限于几个语句并且不可重用(在事件处理程序中经常出现这种情况)时,我会努力使用内联方法。Lamba 表达式还可以广泛用于框架的扩展方法 Enumerable.Select等。并且在使用新的并行库或调用时Where代替Action或使用.FuncControl.Invoke

于 2013-02-20T14:14:48.253 回答
0

第一种方法更容易支持、更复杂和重用。

此外,如何从事件中取消订阅第二种方法也不是很明显

于 2013-02-20T14:03:20.163 回答
0

这是一个类似的主题:delegate 关键字与考虑匿名委托和 lambda 表达式的 lambda 表示法。特别是,答案是:一旦编译,它们之间就没有区别了。

于 2013-02-20T14:06:18.617 回答
0

只要你不需要参数,你甚至可以使用:

myButton.Click += delegate { this.Close(); };

看起来更干净。

但是正如其他人所指出的,使用匿名委托会带来代码可重用性的成本。同样在文章How to: Subscribe to and Unsubscribe from Events中。微软表示:

请务必注意,如果您使用匿名函数订阅某个事件,您将无法轻松取消订阅该事件。要在这种情况下取​​消订阅,必须返回订阅事件的代码,将匿名方法存储在委托变量中,然后将委托添加到事件中。一般来说, 如果您必须在稍后的代码中取消订阅事件,我们建议您不要使用匿名函数来订阅事件

匿名方法的优点之一,也将它们与 lambda 表达式区分开来,是:

...在一种情况下,匿名方法提供了 lambda 表达式中没有的功能。匿名方法使您能够省略参数列表。这意味着可以将匿名方法转换为具有各种签名的委托。 这对于 lambda 表达式是不可能的。

作为上面段落的结论,我们可以说您可以根本不传递任何参数,或者您应该传递事件处理程序的确切签名:

myButton.Click += delegate(object sender, EventArgs e) { this.Close(); };
于 2013-02-20T14:08:41.743 回答