使用lambda表达式与私有方法

我读了一个关于Stack Overflow问题的答案,其中包含以下建议代码:

Action logAndEat = ex => { // Log Error and eat it }; try { // Call to a WebService } catch (SoapException ex) { logAndEat(ex); } catch (HttpException ex) { logAndEat(ex); } catch (WebException ex) { logAndEat(ex); } 

我的问题是:对于LogAndEat使用lambda表达式而不是(在我看来更简单,更明显)私有方法的优点(如果有的话)是什么,如下所示:

 private void LogAndEat(Exception ex) { // Log Error and eat it } 

编辑:感谢目前为止的答案,但只是更清楚地重述我的基本问题:哪种方法更好/你会在这个例子中推荐吗? lambda表达式还是私有方法?

我想你可以认为这个例子中的lambda表达式有点像Pascal的嵌套函数 ,因为它的代码只能通过它声明的方法来执行。

可以从同一个类中的任何方法调用私有方法,而像这样的lambda是当前方法的本地方法,因此显式仅在该上下文中使用。

这是我能想到的唯一优势 – 在预期用途方面明确。

logAndEat捕获的变量否则将成为LogAndEat方法的参数。 你可以认为这是一种forms的讨论。

LogAndEat可以引用定义它的函数中的私有字段。 所以:

 private bool caughtException; Action logAndEat = ex => { caughtException = true; }; try { // Call to a WebService } catch (SoapException ex) { logAndEat(ex); } catch (HttpException ex) { logAndEat(ex); } catch (WebException ex) { logAndEat(ex); } if (caughtException) { Console.Writeline("Ma, I caught an exception!"); } 

这是一个陈腐的例子(!),但这可能比将一堆参数传递给私有方法要简单得多。

要了解使用lambda表达式是否更好(正如我在原始答案中所做的那样)或使用“正确”方法,我们需要根据常见error handling代码的可重用性做出决策。

  • 如果常见error handling代码完全可以被应用程序中不同类中的其他函数重用,则它应该是内部函数或公共函数,如果这使得代码组织更加合理,则可能在不同的类中。

  • 如果常见的error handling代码只能由同一个类中的其他函数重用,那么它应该是同一个类中的私有函数。

  • 如果常见error handling代码不能被任何其他函数重用,并且只能由此特定函数使用,那么您有两个选择。 第一种是使用委托将其封装在函数的边界内,确保函数不泄漏任何实现细节。 第二种方法是在同一个类中使用一个私有函数,注释只能由它所针对的函数调用。

在第三种情况下,没有明确的“最佳方式”,因为两者都是实现相同目标的完美合法方式。 我倾向于在公共代码很小时使用委托和/或你需要代理的一些行为,比如捕获变量。

现在,回到问题,为什么我使用委托编写代码? 我没有关于error handling代码是否可重复使用的信息,所以我认为它不是,并且决定使用委托,因为我认为人们会觉得很容易从这里开始意识到它可能是一个“正确的”方法(如你所知)而如果我展示了使用“正确”的function,人们可能没有意识到代表会成为另一种选择。

很多都归结为个人偏好,没有人能说绝对的方式是正确的方式或错误的方式。

Lambda表达式的行为类似于其他语言中的闭包,关于它们的一个很酷的事情是它们可以访问作用于它们声明的方法的变量。这为您在代码中可以执行的操作增加了很多灵活性,但需要付出代价在调试时无法修改该方法中的代码。

因此,如果您要记录错误,您可能会在某个时间或某个时间发现自己处于该方法的调试器中。 如果你使用lambda,你将无法在运行时修改任何代码 – 因此我的偏好是使用一个单独的私有方法接受exception作为其参数。

感谢大家对我投票的好答案,但我想我总结一下,试着在一个答案中捕捉利弊。

使用lambda表达式(LE)而不是私有方法的优点:

  • LE的范围是声明它的方法,所以如果它只被那个方法使用,那么这个意图是由lambda表达式显式化的(即使可以将一个委托传递给LE,人们仍然可以争论在方法中声明LE的意图是LE的范围是方法)。 也就是说,就其预期用途而言是明确的。
  • Lambda表达式的行为类似于闭包,因此它们可以访问作用于它们声明的方法的变量。这可能比将大量参数传递给私有方法更简洁。
  • 由LE捕获的变量否则将成为私有方法的参数,并且这可以被利用以允许一种forms的currying。

使用lambda表达式而不是私有方法的缺点:

  • 因为LE可以访问作用于包含它们的方法的变量,所以在调试时无法修改调用方法中的代码。

还有一个更主观的可维护性问题,有人可能认为LE并不像大多数开发人员那样理解为私有方法,因此可维护性稍差。 人们还可以争辩说,LE提高了可维护性,因为它被封装在调用它的方法中,而不是整个类可见的私有方法。

IMO我不喜欢微小的私有函数,它们仅用于另一个私有方法,在我的类中徘徊,我发现它们很难看,这就是为什么我在那个样本中使用lambda

我不认为使用lambda而不是函数会对性能产生影响