【发布时间】:2008-12-21 18:05:36
【问题描述】:
C# 3 中的 Lambda 语法使得创建单行匿名方法非常方便。它们是对 C# 2 给我们的冗长的匿名委托语法的明确改进。然而,lambda 的便利性带来了在我们不一定需要它们提供的函数式编程语义的地方使用它们的诱惑。
例如,我经常发现我的事件处理程序是(或至少一开始是)简单的单行器,它们设置状态值,或调用另一个函数,或在另一个上设置属性对象等。对于这些,我应该用另一个简单的函数来混乱我的类,还是应该在我的构造函数中将一个 lambda 填充到事件中?
在这种情况下,lambda 有一些明显的缺点:
- 我无法直接调用我的事件处理程序;它只能由事件触发。当然,对于这些简单的事件处理程序,我几乎不需要直接调用它们。
- 我无法从事件中解开我的处理程序。另一方面,我很少需要解开事件处理程序,所以这不是什么大问题,无论如何。
出于上述原因,这两件事并没有让我很困扰。我可以解决这两个问题,如果它们真的是问题,通过将 lambda 存储在成员委托中,但这会破坏使用 lambdas 的方便和保留类的目的干净整洁。
不过,还有两件事我认为可能不是那么明显,但可能更成问题。
-
每个 lambda 函数在其包含范围内形成一个 闭包。这可能意味着在构造函数中较早创建的临时对象的存活时间比它们需要的时间长得多,因为闭包维护了对它们的引用。现在希望编译器足够聪明,可以从闭包中排除 lambda 不使用的对象,但我不确定。有人知道吗?
再次幸运的是,这并不总是一个问题,因为我不经常在构造函数中创建临时对象。不过,我可以想象一个我做过的场景,并且我无法轻松地将其范围限定在 lambda 之外。
- 可维护性可能会受到影响。重要时刻。如果我将一些事件处理程序定义为函数,而将一些事件处理程序定义为 lambda,我担心这可能会使追踪错误或仅仅理解类变得更加困难。后来,如果我的事件处理程序最终扩展,我要么必须将它们移动到类级函数,要么处理我的构造函数现在包含大量实现我的类功能的代码的事实.
所以我想借鉴其他人的建议和经验,也许是那些具有其他语言经验且具有函数式编程特性的人。这种事情有什么既定的最佳实践吗?您是否会避免在事件处理程序中或在 lambda 明显超出其封闭范围的其他情况下使用 lambda?如果不是,您会在多大的阈值下决定使用实函数而不是 lambda?上述任何陷阱有没有严重伤害任何人?有没有我没有想到的陷阱?
【问题讨论】:
标签: c# lambda event-handling