在Delphi中使用內聯變量(inline variables) 的5個理由


內聯變量聲明(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
   // code
end;

了解所有這些變量的使用位置,初始化時間,是否在之前設置了值等可能令人困惑。在下面的代碼中,我們知道Text變量例如不存在於代碼的開頭,並且僅在結尾使用。在該部分代碼之前,沒有代碼會更改其值:

procedure Test;
begin
   var A, C: Integer;
   // We cannot use Text here
   // lines
   // of
   // code
   
   var Text: string;
   // Text can only be used here
end;

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;
  // AFTER
end;

變量S,I和F是托管類型(字符串,接口和記錄)。編譯器會自動為其添加初始化和完成代碼。

如果您調用TestInlineVars過程一百萬次,將會產生很大的影響。但是,使用上面的代碼,只有在 ACondition為true並且實際執行該塊的情況下,變量才會被初始化減少不必要的代碼被執行。

5.使使用條件指令更容易

此功能甚至可以在小事情上提供幫助。本文引起了我的注意:內聯變量的意外好​​處:條件塊

如果使用編譯器偽指令在每種情況下聲明並使用不同的變量,則還需要在編譯器偽指令周圍包裝變量聲明:

procedure DoesSomething;
var
  {$IFDEF CASE1}
  var1: Integer;
  {$ENDIF}
  {$IFDEF CASE2}
  var2: Integer;
  {$ENDIF
begin
  {$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/

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM