什么时候“拉姆达行动”太多了?
我经常发现自己使用 lambda 作为某种“本地函数”,以便通过重复操作使我的生活更轻松,例如:
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);
我可以愉快地使用 FormatF2 例如,而不是一遍又一遍地编写 String.Format 东西,并节省自己的时间当我需要更改格式时,只有一个地方可以进行编辑。 特别是当我只需要给定函数中的功能时,我非常不愿意将它们变成真正的函数。虽然上面的 lambda 相对较小......有时我有更大的,例如(以下应该将数据添加到表中以进行打印输出):
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 太大了吗?还有哪些其他方法(除了使用实际函数或尝试将数据填充到容器中并循环它们之外)可以避免一遍又一遍地编写相同的代码?
预先感
谢克里斯蒂安
I often find myself using lambdas as some sort of "local functions" to make my life easier with repetetive operations like those:
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);
Instead of writing the String.Format-thing over and over, I can happily blow away with FormatF2 e.g. and save myself time and when I need to change something about the formatting, only one place to make edits.
Especially when I need the functionality in the given function exclusively, I'm very reluctant to turn them into a real function. While the lambdas above were relatively small... sometimes I have larger ones like (the following is supposed to add data to a table for print output):
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;
};
Again, I need this often and all the benefits of above apply, too. However, as you can see, this one is quite long for a lambda expression.. the question is: When do you draw the line? Is my last lambda too much? What other ways (other than using real functions or trying to stuff the data in containers and loop over them) exist to avoid writing the same code over and over again?
Thanks in advance
Christian
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
它是您在一个方法中可能多次使用的东西,并且仅在该方法内使用。我喜欢这个主意。如果它不会使你的代码难以阅读,就这样做。我想说,如果您发现很难看出 lambda 函数的内容与方法的实际内容是什么,您应该重新考虑。在这种情况下,用单独的私有方法将其取出可能会更干净。
最后,这确实是一个品味问题......
It is something you use potentially many times within a method, and only that inside that method. I like this idea. Do it if it doesn't make your code hard to read. I would say that you should reconsider if you find it difficult to see what is the content of the lambda function vs. what is the real content of the method. In that case it might be cleaner to pull it out in a separate private method.
At the end, this is really a matter of taste...
我同意敬畏:对于方法(甚至类)内的小规模重用,这是完美的。就像
string.Format
示例一样。我经常使用这个。这与多次使用局部变量作为中间值基本上是一样的,但是接下来是代码。你的第二个例子似乎有点推动它。不知怎的,这让我感觉私有方法
AddSurfaceData
(可能是静态的,取决于它的用途?)会更合适。这当然超出了你所拥有的背景,所以请运用你自己的良好判断力。I agree with awe: for small scale reuse inside a method (or even a class) this is perfect. Like the
string.Format
examples. I use this quite often. It's basically the same thing as using a local variable for an intermediate value that you use more than once, but then for code.Your second example seems to be pushing it a bit. Somehow this gives me the feeling a private method
AddSurfaceData
(possibly static, depending on its use?) would be a better fit. That is of course outside of the context that you have, so use your own good judgement.Lambda 方法是一种匿名方法。
这意味着您不应该给它命名。
如果您这样做(在您的情况下,您正在使用引用分配名称),那么这只是声明函数的另一种方式。
C#已经有了声明函数的方式,而且不是lambda方式,是新增的
唯一通过参数传递函数并将它们作为返回值返回。
举个例子,在 javascript 中:
或
不同的语法(几乎)相同的东西。
有关为什么它不一样的更多信息: Javascript: var functionName = function( ) {} vs function functionName() {}
另一个例子:在 Haskell 中你可以定义两个函数:
或者
相同的东西(这次我认为它是完全相同的),不同的语法。我更喜欢第一个,它更清晰。
C# 3.5 和 Javascript 一样,受到了很多功能性的影响。恕我直言,其中一些应该被明智地使用。
有人说在引用中进行赋值的本地 lambda 函数可以很好地替代在另一个方法中定义的方法,类似于 Haskell 中的“let”或“where”子句。
我说“相似”是因为两者具有非常不同的语义,例如,在 Haskell 中,我可以使用尚未声明的函数名称,并稍后用“where”定义它,而在 C# 中,我不能使用函数/引用赋值做这个。
顺便说一句,我认为这是个好主意,我并不是禁止使用 lambda 函数,我只是想让人们思考一下。
每种语言都有自己的抽象机制,明智地使用它。
A Lambda method is an anonymous method.
This means that you should not give it a name.
If you are doing that, (in your case, you are assigning a name with your reference), it's just another way to declare a function.
C# has already got a way to declare functions, and it's not the lambda way, which was added
uniquely to pass functions via parameters and returns them as return values.
Think, as an example, in javascript:
or
Different syntax (almost) same thing.
For more information on why it's not the same thing: Javascript: var functionName = function() {} vs function functionName() {}
Another example: in Haskell You can define two functions:
or
Same thing (this time I think it's the very same), different syntax. I prefer the first one, it's more clear.
C# 3.5, as Javascript, has got a lot of functional influences. Some of them should it be used wisely, IMHO.
Someone said local lambda functions with assignment in a reference is a good substitute for a method defined within another method, similar to a "let", or a "where" clause in Haskell.
I say "similar" because the twos have very different semantics, for instance, in Haskell I can use function name which is not declared yet and define it later with "where", while in C#, with function/reference assignment I can't do this.
By the way I think it's a good idea, I'm not banning this use of lambda function, I just want to make people think about it.
Every language has got his abstraction mechanism, use it wisely.
我喜欢这个主意。我没有看到更好的方法来维护代码局部性而不违反 DRY 原则。我认为,如果您不习惯 lambda,那么阅读起来就会更加困难。
I like the idea. I don't see a better way to maintain code locality without violating the DRY principle. And I think it's only harder to read if you're not accustomed to lambdas.
+1 对 nikie re DRY 总体来说很好。
不过我不会使用 PascalCase 命名它们。
但要小心 - 在大多数情况下,您拥有的东西只是裙子中的提取方法或潜在的助手或扩展功能。例如,
GetText
是一个方法,FormatF*
可能是一个辅助方法...+1 on nikie re DRY being good in general.
I wouldnt use PascalCase naming for them though.
Be careful though - in most cases the stuff you have in there is just an Extract Method in a dress or a potential helper or extension function. e.g.,
GetText
is a Method andFormatF*
is probably a helper method...我对这个长例子没有问题。我发现您正在非常优雅地重新包装复合数据。
正是这些简短的内容会促使您的同事研究自愿入院的优势。请声明某种常量来保存您的格式字符串并一遍又一遍地使用“那个 String.Format-thing ”。作为一名 C# 程序员,我知道它的作用,而无需在其他地方寻找自制函数。这样,当我需要知道格式化字符串是什么样子时,我可以只检查该常量。
I have no problem with the long example. I see that you are repackaging compound data very elegantly.
It's the short ones that will drive your colleagues to investigate the advantages of voluntary institutionalization. Please declare some kind of constant to hold your format string and use "that String.Format-thing over and over". As a C# programmer, I know what that does without looking elsewhere for home-spun functions. That way, when I need to know what the formatted string will look like, I can just examine the constant.
我总体上同意volothamp,但除此之外...
想想必须维护您的代码的其他人。我认为这比您的第一个示例更容易理解,并且仍然提供您提到的维护好处:
而您的第二个示例似乎只是声明函数的不同方式。我没有看到比声明辅助方法有任何有用的好处。声明一个辅助方法对于大多数程序员来说会更容易理解。
I agree with volothamp in general, but in addition ...
Think of the other people that have to maintain your code. I think this is easier to understand than your first example and still offers the maintenance benefits you mention:
And your second example appears to be just a different way to declare a function. I don't see any useful benefit over declaring a helper method. And declaring a helper method will be more understandable to the majority of coders.
我个人认为在没有必要的情况下使用 lambda 函数并不好。我个人不会使用 lambda 函数来替换简单的几行程序代码。 Lambda 函数提供了许多增强功能,但使代码阅读起来稍微复杂一些。
我不会用它来替换 string.format。
I personally think its not in good taste to use lambda functions when there is no need for it. I personally wont use a lambda function to replace a simple few lines of procedural code. Lambda functions offer many enhancements, but make the code slightly more complicated to read.
I wouldnt use it to replace string.format.