简体   繁体   English

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

[英]Delphi anonymous methods - pro and cons. Good practices when using closures(anonymus methods) in Delphi

I have a colleague in my team which is extensively using closures in our projects developed in Delphi. 我的团队中有一位同事在Delphi开发的项目中广泛使用了闭包。 Personal, I don't like this because is making code harder to read and I believe that closures should be used ONLY when you need them. 个人,我不喜欢这样,因为使代码更难阅读,我相信只有在你需要时才能使用闭包。

In the other hand I've read Can someone explain Anonymous methods to me? 在另一方面,我读过有人可以向我解释匿名方法吗? and other links related to this, and I'm taking into account that maybe I'm wrong, so I'm asking you to give me some examples when is better to use closures instead of a 'old-fashion' approach (not using closures). 和其他相关的链接,我考虑到可能我错了,所以我要求你给我一些例子什么时候更好地使用闭包而不是'旧时尚'的方法(不使用闭包)。

I believe that this question calls for a very subjective judgement. 我认为这个问题需要一个非常主观的判断。 I am an old-school delphi developer, and inclined to agree with you. 我是一名老式delphi开发人员,并倾向于同意你的看法。 Not only do closures add certain risks (as David H points out in comments) they also reduce readability for all classically trained Delphi developers. 闭包不仅增加了某些风险(正如David H在评论中指出的那样),它们也降低了所有经过专业训练的Delphi开发人员的可读性。 So why were they added to the language at all? 那他们为什么要加入语言呢? In Delphi XE, the syntax-formatting function and closures weren't working well together, for example, and this increased my mistrust of closures; 例如,在Delphi XE中,语法格式化函数和闭包不能很好地协同工作,这增加了我对闭包的不信任; How much stuff gets added to the Delphi compiler, that the IDE hasn't been fully upgraded to support? Delphi编译器添加了多少东西,IDE还没有完全升级到支持? You know you're a cranky old timer when you admit publically that you would have been happy if the Delphi language was frozen at the Delphi 7 level and never improved again. 当你公开承认如果Delphi语言在德尔福7级被冻结并且从未再次改进时,你会很高兴你知道你是一个胡思乱想的旧计时器。 But Delphi is a living, powerful, evolving syntax. 但是Delphi是一种生动,强大,不断发展的语法。 And that's a good thing. 这是一件好事。 Repeat that to yourself when you find the old-crank taking over. 当你发现老曲柄接管时,重复一遍。 Give it a try. 试试看。

I can think of at least ten places where Anonymous methods really make sense and thus, reasons why you should use them, notwithstanding my earlier comment that I mistrust them. 我可以想到至少十个匿名方法真正有意义的地方,因此,你应该使用它们的原因,尽管我之前的评论是我不信任它们。 I will only point out the two that I have decided to personally use, and the limits that I place on myself when I use them: 我只会指出我决定亲自使用的两个,以及我使用它时对自己的限制:

  1. Sort methods in container classes in the Generics.Collections accept an anonymous method so that you can easily provide a sorting bit of logic without having to write a regular (non-anonymous) function that matches the same signature that the sort method expects. Generics.Collections中容器类中的排序方法接受匿名方法,这样您就可以轻松地提供逻辑排序位,而无需编写与排序方法所期望的相同签名匹配的常规(非匿名)函数。 The new generics syntax fits hand in hand with this style, and though it looks alien to you at first, it grows on you and becomes if not exactly really nice to use, at least more convenient than the alternatives. 新的泛型语法与这种风格紧密相关,虽然它起初看起来很陌生,但它会逐渐增长,如果不是非常好用,至少比替代方案更方便。

  2. TThread methods like Synchronize are overloaded, and in addition to supporting a single TThreadMethod as a parameter Thread.Synchronize(aClassMethodWithoutParameters) , it has always been a source of pain to me, to get the parameters into that synchronize method. 像Synchronize这样的TThread方法是重载的,除了支持单个TThreadMethod作为参数Thread.Synchronize(aClassMethodWithoutParameters) ,对于我来说,将参数引入同步方法一直是一个痛苦的根源。 now you can use a closure (anonymous method), and pass the parameters in. 现在你可以使用一个闭包(匿名方法),并传入参数。

Limits that I recommend in writing anonymous methods: 我在编写匿名方法时建议的限制:

A. I have a personal rule of thumb of only ONE closure per function, and whenever there is more than one, refactor out that bit of code to its own method. 答:我有一个个人经验法则,每个函数只有一个闭包,每当有多个闭包时,将这一段代码重构为自己的方法。 This keeps the cyclomatic complexity of your "methods" from going insane. 这使你的“方法”的圈复杂性不会变得疯狂。

B. Also, inside each closure, I prefer to have only a single method invocation, and its parameters, and if I end up writing giant blocks of code, I rewrite those to be methods. B.此外,在每个闭包内部,我更喜欢只有一个方法调用及其参数,如果我最终编写巨大的代码块,我会将它们重写为方法。 Closures are for variable capture, not a carte-blanche for writing endlessly-twisted spaghetti code. 闭包是为了变量捕获,而不是用于编写无休止扭曲的意大利面条代码的全权委托。

Sample sort: 样品分类:

 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;

Update: one comment points to "language uglification", I believe that the uglification refers to the difference between having to write: 更新:一条评论指向“语言uglification”,我相信uglification指的是必须写的区别:

  x.Sort(     
    TMyComparer.Construct(
      function (const L, R: TPair<String, Integer>): integer
      begin
        result := SysUtils.CompareStr(L.Key,R.Key);
      end )   ); 

Instead of, the following hypothetical duck-typed (or should I have said inferred types) syntax that I just invented here for comparison: 而不是,我刚刚在这里发明的用于比较的以下假设的鸭型(或者我应该说的推断类​​型)语法:

  x.Sort( lambda( [L,R], [ SysUtils.CompareStr(L.Key,R.Key) ] ) )

Some other languages like Smalltalk, and Python can write lambdas more compactly because they are dynamically typed. 其他一些语言如Smalltalk和Python可以更简洁地编写lambda,因为它们是动态类型的。 The need for an IComparer, for example, as the type passed to a Sort() method in a container, is an example of complexity caused by the interface-flavor that strongly typed languages with generics have to follow in order to implement traits like ordering, required for sortability. 例如,对IComparer的需求,作为传递给容器中的Sort()方法的类型,是由接口风格引起的复杂性的一个例子,为了实现诸如排序之类的特性,必须遵循强类型语言的泛型,可分拣性要求。 I don't think there was a nice way to do this. 我不认为有一个很好的方法来做到这一点。 Personally I hate seeing procedure, begin and end keywords inside a function invocation parenthesis, but I don't see what else could reasonably have been done. 就个人而言,我讨厌在函数调用括号内查看过程,开始和结束关键字,但我看不出还有什么可以合理地完成。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM