事件处理程序的Lambdas?

P D*_*ddy 9 c# lambda event-handling

C#3中的Lambda语法使得创建单行匿名方法非常方便.它们比C#2给我们的匿名委托语法有了明显的改进.然而,lambda的便利性带来了诱惑,在我们不一定需要它们提供的函数式编程语义的地方使用它们.

例如,我经常发现我的事件处理程序(或者至少是开始时)设置状态值的简单单行,或调用另一个函数,或者在另一个对象上设置属性等.对于这些,我应该杂乱无章我的类有另一个简单的函数,或者我应该在构造函数中将lambda填充到事件中?

在这种情况下,lambdas有一些明显的缺点:

  • 我无法直接调用我的事件处理程序; 它只能由事件触发.当然,在这些简单的事件处理程序的情况下,我几乎不需要直接调用它们.
  • 我无法解开事件中的处理程序.另一方面,我很少需要解开事件处理程序,所以无论如何这都不是问题.

由于上述原因,这两件事并没有太多困扰我.通过将lambda存储在成员委托中,我可以解决这两个问题,如果它们确实存在问题,但这样就会破坏使用lambdas的目的,以保证类的清晰度.

不过,还有另外两件事我认为可能不那么明显,但可能更有问题.

  • 每个lambda函数在其包含范围内形成一个闭包.这可能意味着由于闭包维护对它们的引用,在构造函数中较早创建的临时对象保持活动的时间比它们需要的时间长得多.现在希望编译器足够聪明,可以从lambda不使用的闭包中排除对象,但我不确定.有人知道吗?

    幸运的是,这并不总是一个问题,因为我不经常在我的构造函数中创建临时对象.我可以想象一下我所做的一个场景,而且我不能轻易将它放在lambda之外.

  • 可维护性可能会受到影响.重要时刻.如果我将一些事件处理程序定义为函数,并将一些事件处理程序定义为lambdas,我担心它可能会使追踪错误或仅仅了解类更难.后来,如果我的事件处理程序最终扩展,我要么必须将它们移动到类级函数,要么处理我的构造函数现在包含大量实现我的类功能的代码的事实.

所以我想借鉴其他人的建议和经验,也许是那些具有其他语言经验和函数式编程功能的人.对于这种事情,是否有任何既定的最佳实践?您是否会避免在事件处理程序中使用lambdas,或者在lambda明显超过其封闭范围的其他情况下使用lambdas?如果没有,你会在什么门槛上决定使用真正的函数而不是lambda?上述任何陷阱都会严重咬伤任何人吗?有没有我没想过的陷阱?

Fly*_*wat 2

每个 lambda 函数在其包含范围上形成一个闭包。这可能意味着在构造函数中之前创建的临时对象的存活时间比它们需要的时间长得多,因为闭包维护着对它们的引用。现在希望编译器足够聪明,可以从 lambda 不使用的闭包中排除对象,但我不确定。有人知道吗?

据我所知,C# 编译器要么生成一个匿名方法,要么生成一个匿名内部类,具体取决于它是否需要关闭包含范围。

换句话说,如果您不从 lambda 内部访问包含范围,它就不会生成闭包。

然而,这有点“道听途说”,我希望有更了解 C# 编译器的人参与进来。

尽管如此,旧的 C# 2.0 匿名委托语法做了同样的事情,而且我几乎总是使用匿名委托来处理短事件处理程序。

您已经很好地涵盖了各种优点和缺点,如果您需要取消事件处理程序,请不要使用匿名方法,否则我完全赞成。