我有一个像这样声明的按钮事件:
myButton.Click += new EventHandler(ButtonClicked);
private void ButtonClicked(Object s, EventArgs e)
{
this.Close();
}
我可以这样做:
myButton.Click += (s, e) => this.Close();
我确信使用第二种方式的优点不仅仅是审美。
为什么以及何时应该使用第二种方法因为现在我感到困惑?如果只是为了它的外观,当你的匿名函数体内有多个指令时它看起来不那么清晰。
答案 0 :(得分:4)
技术上没有区别。编译器将在第二种情况下生成处理程序方法。
但坦率地说,我几乎从不使用匿名事件处理程序。为什么?因为他们没有名字。 IDE无法帮助我找到处理事件的地方。你还记得你用匿名方法订阅的确切地点吗?好吧,你可能还记得那个地方。但我打赌你的队友不会。
此外,我不喜欢混合事件处理程序的样式。 Visual Studio为我生成button1_Click
个方法。我不喜欢让一些处理程序以这种方式订阅,有些订阅到位。
我喜欢看事件参数类型。是的取消订阅也很重要。还有更多要点 - 匿名方法对于非常简单的逻辑非常有用(比如在你的情况下关闭表格),但是对于更复杂的东西它们变得非常混乱。我认为将事件处理程序放在适当位置会破坏您的方法的单一责任。它订阅事件,做其他一些事情,并在同一个地方处理事件。我喜欢分开一些东西,以使它们更具可读性和可维护性。
答案 1 :(得分:2)
编译器为此匿名函数(s, e) => this.Close();
生成一种方法,
由您决定使用它,在方法中声明它将允许您访问在该方法中声明的变量。
答案 2 :(得分:1)
嗯,您基本上已经将代理人明确地应用于Click
事件。
您无法在其他任何地方的代码中访问此事件。这样做的主要优点是,您无法在类中的任何其他位置调用您的方法,方法是让您邀请其他“团队成员”访问其代码中的方法,或者可能将其修改符更改为认为应该发生。
如果您希望能够override
一种方法,那么显然内联匿名分配是不利的。
用法或多或少取决于您希望如何处理对逻辑的访问。
答案 3 :(得分:1)
如果你不需要参数,你可以做得更优雅:
myButton.Click += delegate { this.Close(); };
但除了优雅的外观之外没有任何利润。
如果我不需要它们,我不想使用lambda表达式(=>),因为在调试过程中无法更改范围代码。
答案 4 :(得分:1)
匿名函数可以是匿名方法或lambda表达式。 lamba表达式的形式为:
() => //dowork
匿名方法更详细,支持主要是为了向后兼容。匿名函数本身没有值或类型,但它可以转换为委托或表达式树。匿名函数允许我们创建内联方法,这些方法在设置事件处理程序等情况下非常有用。这种方法的内在允许开发人员“在同一个地方”编写代码。换句话说,处理程序在处理事件的位置立即可供读者使用。
当实现仅限于几个语句而不是可重用时(我在事件处理程序中经常出现这种情况),我努力使用内联方法。 Lamba表达式还可以在框架的扩展方法Enumerable.Select
,Where
等中广泛使用。当使用新的parallels库或调用{{1}时,代替Action
或Func
}}。
答案 5 :(得分:0)
第一种方法更容易支持,使更复杂和重用。
如何从事件中取消订阅第二种方法
并不明显答案 6 :(得分:0)
这是一个类似的主题:delegate keyword vs. lambda notation,它考虑匿名委托和lambda表达式。特别地,答案是:一旦编译完成,它们之间就没有区别了。
答案 7 :(得分:0)
只要您不需要参数,您甚至可以使用:
myButton.Click += delegate { this.Close(); };
看起来更干净。
但是,正如其他人所指出的那样,通过使用匿名代理来降低代码可重用性的代价。同样在文章How to: Subscribe to and Unsubscribe from Events中。微软表示:
重要的是要注意你不能轻易取消订阅 如果您使用匿名函数订阅它,则为event。至 在这种情况下取消订阅,有必要返回代码 在您订阅该事件的地方,将匿名方法存储在 委托变量,然后将委托添加到事件中。一般来说, 我们建议您不要使用匿名函数订阅事件,如果您稍后必须取消订阅该事件 在你的代码中指出。
anonymous methods的一个优点是将它们与lambda表达式区分开来:
...有一种情况是匿名方法提供的 lambda表达式中找不到的功能。 匿名方法 使您可以省略参数列表。这意味着匿名 方法可以转换为具有各种签名的委托。 对于lambda表达式,这是不可能的。
作为上面段落的结论,我们可以说你可以根本不传递任何参数,或者你应该传递事件处理程序的确切签名:
myButton.Click += delegate(object sender, EventArgs e) { this.Close(); };