频道分类

Delphi 10.4改进 内联变量声明

作者:admin 来源: 日期:2020/10/12 0:15:00 人气: 标签:

 
旧的var声明方式
从Turbo Pascal 1到现在,根据现有的Pascal语言规则,在编写函数,过程或方法之前,必须在var块中声明所有局部变量声明。
procedure Test;
var
  I: Integer;
begin
  I := 22;
  ShowMessage (I.ToString);
end;

//delphi 10.4 
内联变量声明
可以使用新的内联变量声明语法(允许多个符号)在代码块中直接声明变量:
procedure Test;
begin
  var I, J: Integer;
  I := 22;
  j := I + 20;
  ShowMessage (J.ToString);
end;

看起来差别不大,但是此更改可以带来很多好处。

查看以下内容,了解可以达到的效果。

内联变量初始化

与以前的声明方法相比,最大的变化是可以在一个语句中完成变量内联声明和初始化。

在函数声明中初始化变量更容易看到和理解。

 procedure Test; // declaration and initialization in a single statement
begin
  var I: Integer := 22;
  ShowMessage (I.ToString);
end;

另外,如果仅在代码块中使用变量,则比设置初始值(0或nil)然后分配实际值更有可能。
效率很高。这是因为可以在分配适当的初始值时进行变量声明。
换句话说,如果您以前检查了整个代码块中的所有局部变量,现在只需要检查变量声明位置,直到代码块的末尾。


procedure Test1; // multiple inline declarations (symbols declared when used)
begin
  var I: Integer := 22;
  var J: Integer := 22 + I;
  var K: Integer := I + J;
  ShowMessage (K.ToString);
end;

在嵌套块中声明的内联变量的范围和生存期
范围限制更有意义,因为内联变量仅在代码的始端代码块中可见,而在整个过程或方法中不可见。内联变量声明仅限于已声明的块,不能在该块外部使用。声明的变量的生存期也仅限于仅在块内应用。托管数据类型(接口,字符串,托管记录等)将在子块的末尾而不是在过程或方法的末尾进行处理。

procedure Test2; // scope limited to local block
begin
  var I: Integer := 22;
  if I > 10 then
  begin
    var J: Integer := 3;
    ShowMessage (J.ToString);
  end
  else
  begin
    var K: Integer := 3;
    ShowMessage (J.ToString); // COMPILER ERROR: "Undeclared identifier: J"
  end;
  // J and K not accessible here
end;

如您在上面的最后代码中看到的那样,在begin-end块中声明的变量仅显示在特定的块中,并且在块结束后不应用。之后无法检查if语句末尾的J和K值。

如前所述,这种效果不仅限于可见性问题。像接口引用和记录一样,变量也将在块末尾清除。

procedure Test99;
begin

  // some code

  if (something) then
  begin
    var Intf: IInterface = GetInterface; // Intf.AddRef
    var MRec: TManagedRecord = GetMRecValue; // MRec.Create + MRec.Assign
    UseIntf(Intf);
    UseMRec(MRec);
  end; // Intf.Release and MRec.Destroy are implicitly called at end of scope

  // more code

end; // no additional cleanup

内联变量的类型推断

内联变量的另一个大好处是,编译器可以通过计算在不同情况下分配的表达式或值的类型来推断内联变量的类型。

 procedure Test;
begin
  var I := 22;
  ShowMessage (I.ToString);
end;

通过分析r值表达式(“:=“之后的值)来确定变量的类型。某些数据类型会“扩展”为更大的类型,例如,如上述情况那样,当数值22(ShortInt)扩展为Integer时。通常,如果右侧的公式类型为整数且小于32位,则将该变量声明为整数。如果要使用特定类型的小数字,则可以显式指定类型。

 

此功能可以减少一些整数或字符串的击键,但是对于复杂类型(例如泛型的实例),变量类型推断非常有用。

在下面的代码中,您可以看到MyDictionary变量的TDirtionary类型推断和APair变量的TPair类型推断。
procedure NewTest;
begin
  var MyDictionary := TDictionary.Create;
  MyDictionary.Add ('one', 1);
  var APair := MyDictionary.ExtractPair('one');
  ShowMessage (APair.Value.ToString)
end;


内联常数

像变量一样,常量可以内联声明。它可以应用于类型化或非类型化函数。
 const M: Integer = (L + H) div 2; // single identifier, with type specifier
  const M = (L + H) div 2; // single identifier, without type specifier
 
在For循环中使用内联循环变量声明
可以使用内联变量声明的另一种情况是for循环语句,包括for-to循环和for-in循环。

 for var I: Integer := 1 to 10 do ...
  for var Item: TItemType in Collection do...
 
通过使用类型推断,可以进一步简化代码。

  for var I := 1 to 10 do ...
  for var Item in Collection do ...

使用有限范围的内联变量甚至更有用,例如下面的示例代码。在循环外部使用I变量将导致编译器错误(在大多数情况下,它将给出警告)。
procedure ForTest;
begin
  var total := 0;
  for var I: Integer := 1 to 10 do
    Inc (Total, I);
  ShowMessage (total.ToString);
  ShowMessage (I.ToString); // compiler error: Undeclared Identifier ‘I’
end;

内联声明摘要
内联变量声明以及类型推断和局部作用域将对Delphi语言进行全新的更改。Pascal源代码的可读性仍然是保留的关键原则,但这是在核心级别对语言进行现代化的一项重要更改。与传统的编码样式相比,内联变量具有许多优势。 
尽管仍然保持源代码完整并遵循声明开发人员的传统方式没问题:不是旧代码或编写方式错误,内联变量声明无疑将是一个新机会。我只想说...就我而言,要回到旧版本的Delphi已经很困难。