本文整理自网络,侵删。
内联变量声明(Inline Variable Declaration)是Delphi Rio 10.3中引入的功能。它是什么?
简而言之,可以在代码的任何行中声明一个变量。也就是说,您可以在begin..end块中以这种方式声明变量:
procedure Test;begin var I: Integer; I := 22; ShowMessage (I.ToString);end;许多人已经了解了此功能的工作原理,但不了解为什么它很有趣。在本文中,我将向您展示此新功能,重点介绍其带来的优势。
1.整理您的代码该变量只能从声明点访问。对于许多人来说,这更好地组织在一个大的方法中的代码,因为它可以更好地了解那里正在使用的变量。考虑以下代码:
procedure Test;var A, B, C, D, E: Integer; Found, Done, Excluded: Boolean; Text: string;begin // many // lines // of // codeend;了解所有这些变量的使用位置,初始化时间,是否在之前设置了值等可能令人困惑。在下面的代码中,我们知道Text变量例如不存在于代码的开头,并且仅在结尾使用。在该部分代码之前,没有代码会更改其值:
procedure Test;begin var A, C: Integer; // We cannot use Text here // lines // of // code var Text: string; // Text can only be used hereend;2.尽量减少错误您是否曾经做过这样的事情:
procedure Test;var I: Integer;begin for I := 0 to Count - 1 do Process; DoSomethingWithI(I);end;也就是说,在循环结束后使用for变量。这是不安全的,尽管编译器对此发出警告,但许多人忽略了它。通过声明for变量内联,它将仅在for内有效,而在块外使用它将导致编译错误:
procedure Test;begin for var I: Integer := 0 to Count - 1 do Process; DoSomethingWithI(I); // Compile error!!!end;上面的代码的好处在于,变量的范围仅限于声明它们的块。这样可以最大程度地减少出错的机会。例如,假设您有如下代码:
procedure Test;var I: Integer;begin I := CalculateSomething; Persist(I); // many lines below... Log(I);end;然后,您最终需要以第一部分仅在指定条件下执行的方式重构代码。您认为该变量I仅在此处使用,并执行以下操作:
procedure Test;var I: Integer;begin if Condition then begin I := CalculateSomething; Persist(I); end; // many lines below... Log(I);end;在那里,您忘记了最后一行,也许I的值不是您所期望的。如果在块外使用变量,则将变量的范围更改为块会产生编译错误,这将立即向您显示问题,因此您可以做出决定:
procedure Test;begin if Condition then begin var I: Integer; I := CalculateSomething; Persist(I); end; // many lines below... Log(I); // Compile error!end;3.打字少谁不希望提高生产力?如果可以少键入一些内容来声明变量,为什么不呢?现在,您可以同时声明和初始化变量:
procedure Test;begin var I: Integer := 22; ShowMessage (I.ToString);end;但不仅如此。还有一个类型推断,这意味着在大多数情况下,在声明它时不需要包括变量类型。只需使用值初始化变量,Delphi就会知道变量类型。
看起来没什么大不了的?想象一下一个变量类型使用大量泛型的情况:
procedure NewTest;var MyDictionary: TObjectDictionary<string, TObjectList<TMyAmazingClass>>; Pair: TPair<string, TObjectList<TMyAmazingClass>>; List: TObjectList<TMyAmazingClass>;begin MyDictionary := TObjectDictionary<string, TObjectList<TMyAmazingClass>>.Create; MyDictionary.Add('one', CreateList); Pair := MyDictionary.ExtractPair('one'); List := Pair.Value; ShowMessage(List.Count.ToString);end;使用内联变量和类型推断,您可以通过以下方式重写代码:
procedure NewTest;begin var MyDictionary := TObjectDictionary<string, TObjectList<TMyAmazingClass>>.Create; MyDictionary.Add('one', CreateList); var Pair := MyDictionary.ExtractPair('one'); var List := Pair.Value; ShowMessage(List.Count.ToString);end;更好,不是吗?
4.提高性能变量属于更有限范围的事实(在begin..end块内)甚至可以提高代码性能!
您可以在这篇出色的文章中看到更多详细信息:内联变量可以提高性能。概括来说:仅当代码执行进入块时,变量才会初始化;仅在块退出时,变量才会最终确定。在此代码中,例如:
procedure TestInlineVars(const ACondition: Boolean);begin // BEFORE if (ACondition) then begin var S := 'Inline String'; var I: IInterface := TInterfacedObject.Create; var F: TFoo; F.S := 'Managed Record'; end; // AFTERend;变量S,I和F是托管类型(字符串,接口和记录)。编译器会自动为其添加初始化和完成代码。
如果您调用TestInlineVars过程一百万次,将会产生很大的影响。但是,使用上面的代码,只有在 ACondition为true并且实际执行该块的情况下,变量才会被初始化。减少不必要的代码被执行。
5.使使用条件指令更容易此功能甚至可以在小事情上提供帮助。本文引起了我的注意:内联变量的意外好??处:条件块。
如果使用编译器伪指令在每种情况下声明并使用不同的变量,则还需要在编译器伪指令周围包装变量声明:
procedure DoesSomething;var {$IFDEF CASE1} var1: Integer; {$ENDIF} {$IFDEF CASE2} var2: Integer; {$ENDIFbegin {$IFDEF CASE1} // use var1 {$ENDIF} {$IFDEF CASE2} // use var2 {$ENDIF}end;无聊吧?我认为这更容易:
procedure DoesSomething;begin {$IFDEF CASE1} var1: Integer; // use var1 {$ENDIF} {$IFDEF CASE2} var2: Integer; // use var2 {$ENDIF}end;我认为,内联变量在未在此处列出的特定情况下仍会带来其他细微的好处。如果您认为还有其他好处,请发表评论。如果您不同意并且认为内联变量对于Delphi不是好消息,请也发表您的评论。只是不要忘记一件事:如果您不喜欢它,那就不要使用它!
原文:https://landgraf.dev/en/5-reasons-to-use-inline-variables-in-delphi/
相关阅读 >>
解决 Delphi 程序在不同操作系统中 shellexecute 调用 chrome.exe 偶尔无效的问题
github上通过星级评估排名前10的最受欢迎的开源Delphi项目
更多相关阅读请进入《Delphi》频道 >>