内联变量声明(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不是好消息,请也发表您的评论。只是不要忘记一件事:如果您不喜欢它,那就不要使用它!
在Delphi中使用内联变量(inline variables) 的5个理由
原文:https://www.cnblogs.com/rtcmw/p/12158078.html