我的团队中有一位同事在Delphi开发的项目中广泛使用了闭包。个人,我不喜欢这样,因为使代码更难阅读,我相信只有在你需要时才能使用闭包。
另一方面,我已经阅读了Can someone explain Anonymous methods to me?以及与此相关的其他链接,我考虑到可能我错了,所以我要求你给我一些例子。更好地使用闭包而不是“旧时尚”方法(不使用闭包)。
答案 0 :(得分:11)
我认为这个问题需要一个非常主观的判断。我是一名老式delphi开发人员,并倾向于同意你的看法。闭包不仅增加了某些风险(正如David H在评论中指出的那样),它们也降低了所有经过专业训练的Delphi开发人员的可读性。那他们为什么要加入语言呢?例如,在Delphi XE中,语法格式化函数和闭包不能很好地协同工作,这增加了我对闭包的不信任; Delphi编译器添加了多少东西,IDE还没有完全升级到支持?当你公开承认如果Delphi语言在德尔福7级被冻结并且从未再次改进时,你会很高兴你知道你是一个胡思乱想的旧计时器。但是Delphi是一种生动,强大,不断发展的语法。这是一件好事。当你发现老曲柄接管时,重复一遍。试一试。
我可以想到至少十个匿名方法真正有意义的地方,因此,你应该使用它们的原因,尽管我之前的评论是我不信任它们。我只会指出我决定亲自使用的两个,以及我使用它时对自己的限制:
Generics.Collections中容器类中的排序方法接受匿名方法,这样您就可以轻松地提供逻辑排序位,而无需编写匹配相同签名的常规(非匿名)函数。 sort方法期望。新的泛型语法与这种风格紧密相关,虽然它一开始看起来很陌生,但它会逐渐增长,如果不是非常好用,至少比替代方案更方便。
像Synchronize这样的TThread方法被重载了,除了支持单个TThreadMethod作为参数Thread.Synchronize(aClassMethodWithoutParameters)
之外,对于我来说,将参数引入同步方法一直是一个痛苦的根源。现在你可以使用一个闭包(匿名方法),并传递参数。
我建议写匿名方法的限制:
一个。我有一个个人经验法则,每个函数只有一个闭包,每当有多个闭包时,将该位代码重构为自己的方法。这使你的“方法”的圈复杂性不会变得疯狂。
B中。另外,在每个闭包内部,我更喜欢只有一个方法调用及其参数,如果我最终编写巨大的代码块,我会将它们重写为方法。闭包是为了变量捕获,而不是用于编写无休止扭曲的意大利面条代码的全权委托。
样品分类:
var
aContainer:TList<TPair<String, Integer>>;
begin
aContainer.Sort(
TMyComparer.Construct(
function (const L, R: TPair<String, Integer>): integer
begin
result := SysUtils.CompareStr(L.Key,R.Key);
end ) {Construct end} ); {aContainer.Sort end}
end;
更新:一条评论指向“语言丑化”,我相信uglification指的是必须写的区别:
x.Sort(
TMyComparer.Construct(
function (const L, R: TPair<String, Integer>): integer
begin
result := SysUtils.CompareStr(L.Key,R.Key);
end ) );
而不是以下假设的鸭型(或者我应该说的推断类型)语法,我刚刚在这里发明用于比较:
x.Sort( lambda( [L,R], [ SysUtils.CompareStr(L.Key,R.Key) ] ) )
其他一些语言如Smalltalk和Python可以更紧凑地编写lambdas,因为它们是动态类型的。例如,对IComparer的需求,作为传递给容器中的Sort()方法的类型,是一个由接口风格引起的复杂性的例子,为了实现诸如排序之类的特性,必须遵循强类型语言的泛型,可分拣性要求。我不认为有一个很好的方法来做到这一点。就个人而言,我讨厌在函数调用括号内查看过程,开始和结束关键字,但我看不出还有什么可以合理地完成。