什么时候“lambda行动”太多了?

时间:2009-11-12 08:15:50

标签: c# coding-style lambda

我经常发现自己使用lambdas作为某种“本地功能”,通过像以下那样的重复操作让我的生活更轻松:

Func<string, string> GetText = (resource) => this.resourceManager.GetString(resource);
Func<float, object, string> FormatF1 = (f, o) => String.Format("{0:F1} {1}", f, o);
Func<float, object, string> FormatF2 = (f, o) => String.Format("{0:F2} {1}", f, o);

不是一遍又一遍地写String.Format-thing,我很乐意用FormatF2吹掉,例如:并节省自己的时间,当我需要改变格式的一些东西,只有一个地方进行编辑。 特别是当我只需要给定函数中的功能时,我非常不愿意将它们变成一个真正的函数。虽然上面的lambdas相对较小...有时我会有较大的那些(以下应该将数据添加到表中以供打印输出):

Action<string, string, string> AddSurfaceData = (resource, col, unit) => {
    renderTable.Cells[tableRowIndex, 0].Text = "\t" + this.GetText(resource);
    renderTable.Cells[tableRowIndex, 1].Text = FormatF2(paraHydReader.GetFloat(paraHydReader.GetOrdinal(col)), "");
    renderTable.Cells[tableRowIndex, 1].Style.TextAlignHorz = C1.C1Preview.AlignHorzEnum.Right;
    renderTable.Cells[tableRowIndex, 2].Text = " " + this.GetText(unit);
    renderTable.Cells[tableRowIndex, 2].Style.TextAlignHorz = C1.C1Preview.AlignHorzEnum.Left;
    ++tableRowIndex;
};

同样,我经常需要这个,上面的所有好处也适用。但是,正如你所看到的,这个对于lambda表达式来说很长。问题是:你什么时候画线?我的最后一个lambda太多了吗?还有什么其他方法(除了使用实际函数或尝试将数据填充到容器中并循环遍历它们)以避免一遍又一遍地编写相同的代码?

提前致谢

基督教

8 个答案:

答案 0 :(得分:11)

这是您在方法中可能多次使用的东西,而且只是在该方法中使用的东西。我喜欢这个主意。如果它不会使您的代码难以阅读,请执行此操作。我会说你应该重新考虑一下,如果你发现很难看出lambda函数的内容与方法的真实内容是什么。在这种情况下,将它拉出一个单独的私有方法可能更干净。

最后,这真的是一种品味......

答案 1 :(得分:6)

我同意敬畏:对于方法(甚至是类)中的小规模重用,这是完美的。与string.Format示例一样。我经常使用这个。这与使用多次使用的中间值的局部变量but then for code基本相同。

你的第二个例子似乎是在推动它。不知怎的,这让我感觉私有方法AddSurfaceData(可能是静态的,取决于它的用途?)会更合适。这当然超出了你的背景,所以要运用自己的判断力。

答案 2 :(得分:4)

Lambda方法是一种匿名方法。

这意味着你不应该给它起个名字。

如果你这样做,(在你的情况下,你正在为你的引用指定一个名字),这只是宣告一个函数的另一种方式。

C#已经有了一种声明函数的方法,并且它不是lambda方式,而是添加了 唯一通过参数传递函数并将它们作为返回值返回。

以javascript:

为例
function f(var1,var2,...,varX)
{
    some code
}

var f = function() {
    some code    
}

不同的语法(几乎)相同的东西。

有关为什么不一样的更多信息:Javascript: var functionName = function() {} vs function functionName() {}

另一个例子:在Haskell中你可以定义两个函数:

 function1 :: Int -> Int
 function1 x = x + 2

 function2 :: Int -> Int
 function2 = \x -> x + 2

同样的事情(这次我认为它是一样的),不同的语法。我更喜欢第一个,它更清楚。

C#3.5,作为Javascript,有很多功能影响。其中一些应该明智地使用,恕我直言。

有人说在引用中赋值的本地lambda函数是另一种方法中定义的方法的一个很好的替代,类似于Haskell中的“let”或“where”子句。

我说“相似”因为两个语义有很大不同,例如,在Haskell中我可以使用尚未声明的函数名称,稍后用“where”定义它,而在C#中,函数/引用赋值我不能这样做。

顺便说一下,我认为这是一个好主意,我不是禁止使用lambda函数,我只想让人们考虑一下。 每种语言都有自己的抽象机制,明智地使用它。

答案 3 :(得分:2)

我喜欢这个主意。在没有违反DRY原则的情况下,我没有看到更好的方法来维护代码局部性。而且我认为如果你不习惯lambdas,那就更难读了。

答案 4 :(得分:2)

+1 nikie re DRY一般情况良好。

我不会为他们使用PascalCase命名。

虽然要小心 - 在大多数情况下,你所拥有的东西只是服装中的提取方法或潜在的助手或扩展功能。例如,GetText是一种方法,FormatF*可能是辅助方法......

答案 5 :(得分:2)

我对长长的例子没有任何问题。我看到你正在非常优雅地重新打包复合数据。

这些短篇小说将推动你的同事调查自愿制度化的优势。请声明某种常量来保存您的格式字符串并使用“那个String.Format-thing一遍又一遍”。作为一名C#程序员,我知道在没有寻找其他家庭旋转功能的情况下会做些什么。这样,当我需要知道格式化字符串的样子时,我可以检查常量。

答案 6 :(得分:1)

我一般同意volothamp,但另外......

想想其他人必须维护你的代码。我认为这比你的第一个例子更容易理解,仍然提供你提到的维护好处:

String.Format(this.resourceManager.GetString("BasicFormat"), f, o);
String.Format(this.resourceManager.GetString("AdvancedFormat"), f, o);

你的第二个例子似乎只是宣告一个函数的另一种方式。我没有看到任何有用的好处,而不是声明一个帮助方法。并且大多数编码人员都会更容易理解帮助方法。

答案 7 :(得分:0)

我个人认为在不需要它的情况下使用lambda函数并不是很好。我个人不会使用lambda函数来替换简单的几行过程代码。 Lambda函数提供了许多增强功能,但使代码阅读稍微复杂一些。

我不会用它来替换string.format。