Delphi匿名方法 - 赞成和利弊。在Delphi中使用闭包(anonymus方法)时的良好实践

时间:2011-10-19 08:48:46

标签: delphi closures anonymous-methods

我的团队中有一位同事在Delphi开发的项目中广泛使用了闭包。个人,我不喜欢这样,因为使代码更难阅读,我相信只有在你需要时才能使用闭包。

另一方面,我已经阅读了Can someone explain Anonymous methods to me?以及与此相关的其他链接,我考虑到可能我错了,所以我要求你给我一些例子。更好地使用闭包而不是“旧时尚”方法(不使用闭包)。

1 个答案:

答案 0 :(得分:11)

我认为这个问题需要一个非常主观的判断。我是一名老式delphi开发人员,并倾向于同意你的看法。闭包不仅增加了某些风险(正如David H在评论中指出的那样),它们也降低了所有经过专业训练的Delphi开发人员的可读性。那他们为什么要加入语言呢?例如,在Delphi XE中,语法格式化函数和闭包不能很好地协同工作,这增加了我对闭包的不信任; Delphi编译器添加了多少东西,IDE还没有完全升级到支持?当你公开承认如果Delphi语言在德尔福7级被冻结并且从未再次改进时,你会很高兴你知道你是一个胡思乱想的旧计时器。但是Delphi是一种生动,强大,不断发展的语法。这是一件好事。当你发现老曲柄接管时,重复一遍。试一试。

我可以想到至少十个匿名方法真正有意义的地方,因此,你应该使用它们的原因,尽管我之前的评论是我不信任它们。我只会指出我决定亲自使用的两个,以及我使用它时对自己的限制:

  1. Generics.Collections中容器类中的排序方法接受匿名方法,这样您就可以轻松地提供逻辑排序位,而无需编写匹配相同签名的常规(非匿名)函数。 sort方法期望。新的泛型语法与这种风格紧密相关,虽然它一开始看起来很陌生,但它会逐渐增长,如果不是非常好用,至少比替代方案更方便。

  2. 像Synchronize这样的TThread方法被重载了,除了支持单个TThreadMethod作为参数Thread.Synchronize(aClassMethodWithoutParameters)之外,对于我来说,将参数引入同步方法一直是一个痛苦的根源。现在你可以使用一个闭包(匿名方法),并传递参数。

  3. 我建议写匿名方法的限制:

    一个。我有一个个人经验法则,每个函数只有一个闭包,每当有多个闭包时,将该位代码重构为自己的方法。这使你的“方法”的圈复杂性不会变得疯狂。

    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()方法的类型,是一个由接口风格引起的复杂性的例子,为了实现诸如排序之类的特性,必须遵循强类型语言的泛型,可分拣性要求。我不认为有一个很好的方法来做到这一点。就个人而言,我讨厌在函数调用括号内查看过程,开始和结束关键字,但我看不出还有什么可以合理地完成。