C# 事件处理程序的Lambdas?
C#3中的Lambda语法使得创建一行匿名方法非常方便。与C#2给我们的更冗长的匿名委托语法相比,它们是一个明显的改进。然而,lambdas的便利性带来了在我们不一定需要它们提供的函数式编程语义的地方使用它们的诱惑 例如,我经常发现我的事件处理程序是(或至少一开始是)简单的一行程序,用于设置状态值、调用另一个函数或设置另一个对象的属性等。对于这些,我应该用另一个简单函数来混乱我的类,还是应该在构造函数中将lambda填充到事件中 在这种情况下,lambdas有一些明显的缺点:C# 事件处理程序的Lambdas?,c#,lambda,event-handling,C#,Lambda,Event Handling,C#3中的Lambda语法使得创建一行匿名方法非常方便。与C#2给我们的更冗长的匿名委托语法相比,它们是一个明显的改进。然而,lambdas的便利性带来了在我们不一定需要它们提供的函数式编程语义的地方使用它们的诱惑 例如,我经常发现我的事件处理程序是(或至少一开始是)简单的一行程序,用于设置状态值、调用另一个函数或设置另一个对象的属性等。对于这些,我应该用另一个简单函数来混乱我的类,还是应该在构造函数中将lambda填充到事件中 在这种情况下,lambdas有一些明显的缺点: 我不能直接调用我
- 我不能直接调用我的事件处理程序;它只能由事件触发。当然,对于这些简单的事件处理程序,我几乎不需要直接调用它们
- 我无法将我的处理程序与事件解除挂钩。另一方面,我很少需要解开事件处理程序的挂钩,所以这也不是什么大问题
- 每个lambda函数在其包含范围上形成一个闭包。这可能意味着,由于闭包维护对临时对象的引用,在构造函数早期创建的临时对象保持活动的时间比它们需要的时间长得多。现在希望编译器足够聪明,可以从lambda不使用的闭包中排除对象,但我不确定。有人知道吗 幸运的是,这并不总是一个问题,因为我不经常在构造函数中创建临时对象。我可以想象这样一个场景,虽然我做到了,但我不能轻易地在lambda之外对其进行观察
- 可维护性可能会受到影响。重要时刻。如果我将一些事件处理程序定义为函数,而将一些事件处理程序定义为lambdas,我担心这可能会使跟踪bug或仅仅理解类变得更加困难。稍后,如果我的事件处理程序最终扩展,我将不得不将它们移动到类级函数,或者处理这样一个事实,即我的构造函数现在包含大量实现类功能的代码
您已经很好地介绍了各种优缺点,如果您需要解开事件处理程序的挂钩,请不要使用匿名方法,否则我完全赞成。我通常有一个例程专门用于连接事件处理程序。其中,我使用匿名委托或lambda作为实际的处理程序,使它们尽可能短。这些处理程序有两个任务:
这样,我就避免了将我的类名称空间与无法干净地用于其他目的的事件处理程序方法混为一谈,并迫使自己考虑我实现的操作方法的需要和目的,通常会产生更干净的代码 lambdas的大多数相同特性同样适用于您可以使用它们的其他地方。如果事件处理程序不适合他们,我想不出更好的了。它是一个单点独立的逻辑单元,位于它的单点上 在许多情况下,事件的目的是获得一个小的上下文包,结果证明它正好适合手头的工作
我认为这是重构意义上的“好气味”之一。
< P>根据编译器的一个小实验,我会说编译器足够聪明,可以创建一个闭包。我所做的是一个简单的构造函数,它有两个不同的lambda,用于List.Find()中的谓词 第一个lamdba使用硬编码值,第二个使用构造函数中的参数。第一个lambda作为类上的私有静态方法实现。第二个lambda被实现为执行关闭的类 因此,您认为编译器足够聪明的假设是正确的。Concpublic class UserIsUnhappy : Notification { public int unhappiness; }