DELPHI盒子
!实时搜索: 盒子论坛 | 注册用户 | 修改信息 | 退出
检举帖 | 全文检索 | 关闭广告 | 捐赠
技术论坛
 用户名
 密  码
自动登陆(30天有效)
忘了密码
≡技术区≡
DELPHI技术
移动应用开发
Web应用开发
数据库专区
报表专区
网络通讯
开源项目
论坛精华贴
≡发布区≡
发布代码
发布控件
文档资料
经典工具
≡事务区≡
网站意见
盒子之家
招聘应聘
信息交换
论坛信息
最新加入: botbead
今日帖子: 18
在线用户: 22
导航: 论坛 -> 移动应用开发 斑竹:flyers,iamdream  
作者:
男 earthsbest (全能中间件) ▲▲△△△ -
注册会员
2020/1/7 9:50:00
标题:
在Delphi中使用内联变量(inline variables) 的5个理由 浏览:1153
加入我的收藏
楼主:     内联变量声明 (Inline Variable Declaration) 是 Delphi Rio 10.3 中引入的功能,简而言之,可以在代码的任何行中声明一个变量,也就是说,您可以在begin..end块中以这种方式声明变量:

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

或者:

procedure Test;
begin
  var Obj := TObject.Create;
  // 你的更多代码....
end;
    Delphi Rio 10.3 发布后,大家对这个功能褒贬不一:有人说太好了,早该加入了,与时俱进,紧跟历史发展潮流和时代前进步伐。有人说,它破坏了Pascal 语言的严谨性,随处定义变量就像随地大小便一样让人讨厌。
    之前看到一篇洋人写的《在Delphi中使用内联变量(inline variables) 的5个理由》拿出来和大家一起分享和探讨,说说你喜欢或者不喜欢的理由,只是不要忘记一件事:如果您不喜欢它,那就不要使用它!

《在Delphi中使用内联变量(inline variables) 的5个理由》
原文:
https://landgraf.dev/en/5-reasons-to-use-inline-variables-in-delphi
译文:
http://www.cnblogs.com/rtcmw/p/12158078.html
----------------------------------------------
Delphi4Linux Delphi三层/FireDAC 技术群:734515869 http://www.cnblogs.com/rtcmw
作者:
男 keymark (keymark) ▲△△△△ -
注册会员
2020/1/7 9:58:19
1楼: 我就觉得 代码 长了 不用切换到 begin 上加变量方便。。。
----------------------------------------------
https://www.cnblogs.com/marklove/
作者:
男 dbyoung (dbyoung) ★☆☆☆☆ -
普通会员
2020/1/7 11:05:17
2楼: 不喜欢它,极少使用。

一个过程最好不要超过20行代码。超过20行,说明你的代码有问题(不是绝对的)。
提示、警告都处理掉,

平时就养成良好的编程习惯,这些都不是问题。
----------------------------------------------
Delphi7爱好者
作者:
男 earthsbest (全能中间件) ▲▲△△△ -
注册会员
2020/1/7 11:34:57
3楼: 用内联变量代码更少,特别是类型很长时尤为明显,比如泛型:
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;

感受下,第二种是不是简洁了很多。
----------------------------------------------
Delphi4Linux Delphi三层/FireDAC 技术群:734515869 http://www.cnblogs.com/rtcmw
作者:
男 zwjchinazwj (蒲石) ★☆☆☆☆ -
普通会员
2020/1/7 11:45:35
4楼: 曾经我写C++,c=a+++b可以让三四行代码变成一行,简单太帅了
----------------------------------------------
-
作者:
男 earthsbest (全能中间件) ▲▲△△△ -
注册会员
2020/1/7 11:48:43
5楼: 楼上,和C家族的自增自减运算符不同的是,内联变量使代码简洁,但并不牺牲可读性。
----------------------------------------------
Delphi4Linux Delphi三层/FireDAC 技术群:734515869 http://www.cnblogs.com/rtcmw
作者:
男 zwjchinazwj (蒲石) ★☆☆☆☆ -
普通会员
2020/1/7 12:29:24
6楼: 0基的字符串,能更符合c++的习惯.  ARC也的确方便内存管理

很多事情都有其有利的一面,也有不利的一面。重要的是使用者可以根据自己的需要加以选择。

所以,你觉得适合你就好。
----------------------------------------------
-
作者:
男 wang_80919 (Flying Wang) ▲▲▲▲▲ -
普通会员
2020/1/7 16:55:56
7楼: 顶 5 楼。可读性很重要。
----------------------------------------------
(C)(P)Flying Wang
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2020/1/7 18:13:36
8楼: 2楼说得有道理。

一些限制,是让代码更容易读,也更不容易出错。我最欣赏的就是 DELPHI 的变量集中一个地方定义。随地定义变量,读代码的时候,到处找这个变量是哪里定义的,很烦。

对于 PASCAL 来说,有一个限制,在语法上是没有限制的:全局变量。但作为写代码的人,就算语法上不限制,自己也应该限制自己。否则代码容易出问题,而且出了问题也不好查。
----------------------------------------------
-
作者:
男 chencong5025 (Nicosoft) ▲▲△△△ -
注册会员
2020/1/7 19:42:28
9楼: 语法智障提示  就是不用的理由。

红色波浪线很碍眼
----------------------------------------------
-
作者:
男 kentty (kentty) ★☆☆☆☆ -
普通会员
2020/1/7 21:13:57
10楼: @chengcong5025 红色波浪线的问题10.3.3还没有搞定? 英巴还把这个inline variable当作一个新特性宣传,结果自家的ide都不识别。。。。
----------------------------------------------
-
作者:
男 chencong5025 (Nicosoft) ▲▲△△△ -
注册会员
2020/1/8 2:16:17
11楼: @kentty

一如既往的 智障提示 = =#
----------------------------------------------
-
作者:
男 wntee (wntee) ▲▲▲△△ -
注册会员
2020/1/8 9:48:55
12楼: 别的不说,我原来一个2000多行的WndProc过程改用内联变量后,效率提升明显
不管你用不用,内联变量都是趋势,也是其它高级语言都具备的功能
不要有先入为主的思维定势
----------------------------------------------
当前后左右都没有路时,命运一定是鼓励你向上飞了...
作者:
男 looper (keyo) ★☆☆☆☆ -
盒子活跃会员
2020/1/8 10:50:17
13楼: 这种代码要是想移植到Lazarus...
----------------------------------------------
虽千万人吾往矣!
作者:
男 wang_80919 (Flying Wang) ▲▲▲▲▲ -
普通会员
2020/1/8 10:56:37
14楼: 8 楼 ,你的理由 正好 需要 inline var
因为 变量 作用范围 最好 别 都在 一个函数内。应该是一个代码段内。
而且 变量多了 定义 和 使用 就乱了。
----------------------------------------------
(C)(P)Flying Wang
作者:
男 hs_kill (lzl_17948876) ★☆☆☆☆ -
普通会员
2020/1/8 12:29:02
15楼: 顶9楼, 智障提示才是不用的理由..满屏的红波浪线, 还有单元错误提示
----------------------------------------------
http://www.cnblogs.com/lzl_17948876/
作者:
男 doorkey (DoorKey) ★☆☆☆☆ -
盒子活跃会员
2020/1/8 13:39:43
16楼: 内联变量---这个功能真的好用。很多变量就应该局部定义就好,都在函数头定义,代码一多也是很不直观,代码反而不好阅读。
----------------------------------------------
QQ: 9717005 我的Blog:http://www.cnblogs.com/anydelphi/
作者:
男 yxsoft (yxsoft) ★☆☆☆☆ -
盒子活跃会员
2020/1/8 14:57:56
17楼: 我觉得就一种地方用比较好,条件编译用到变量的时候
----------------------------------------------
Great!
作者:
男 emailx45 (emailx45) ▲▲▲△△ -
注册会员
2020/1/9 5:38:36
18楼: I believe that is a new view about OP, but..... really is not so good and is a bad pratice create GLOBAL VARIABLES for any place on code.

But, INLINE definition should be used WHERE YOU REALLY IS ON CONTROL IN YOUR CODE or MAYBE ONLY YOUR CODE IS THREAD-SAFE to avoid memory leaks or some bug, for example, changing the value for your fault...

But, if you dont like this, dont worry. 

OP still the same in your traditional code.
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!
作者:
男 emailx45 (emailx45) ▲▲▲△△ -
注册会员
2020/1/9 5:43:07
19楼: here my sample using INLINE variables and your scope

unit Unit1;

interface

uses
  Winapi.Windows,
  Winapi.Messages,
  System.SysUtils,
  System.Variants,
  System.Classes,
  Vcl.Graphics,
  Vcl.Controls,
  Vcl.Forms,
  Vcl.Dialogs,
  Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    ComboBox1: TComboBox;
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    private
      procedure prcPrivateProc(lVarA: Integer);
    public
      procedure prcPublicProc(lVarB: Integer);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
//
{
  //**********
  procedure prcSub_Procedure1;
  begin
  s := s + ', i dont work in prcSub_Procedure1! See my definition is below (later)';
  end;
  //**********
}
//

var // <---
  // i: Integer;  // if defined here, will conflict with "i" defined in "var inline below
  //
  s: String; // scope global to your procedure, same if used in sub-procedures defined here!

  lUrl: String;
  //
  // **********
  procedure prcSub_Procedure2;
  begin
    s := s + ', im re-writed in prcSub_Procedure2! See my definition is above (before)';
  end;

// **********
begin
  //
  // DONT WORRY ABOUT "line red" in your editor screen!
  //
  lUrl := 'http://www.idera.com&#39;;
  //
  ComboBox1.Items.Clear;

  begin // ITS NOT NECESSARY, AND DONT HELP YOU AND NOTHING HERE!
    //
    var  ext := LowerCase(ExtractFileExt(lUrl));

    ShowMessage(ext); // works!

    prcPrivateProc(ext.ToInteger()); // works!

    prcPublicProc(ext.ToInteger()); // works!

    for var i := 0 to 10 do { var "inline" only works on the "block" is defined! }
    begin // "BEGIN_NECESSARY" --> if commented, i is "out of scope" too
      //
      ComboBox1.Items.Add(Format('Value to i = %d', [i]));
      //
      ComboBox1.ItemIndex := i; // "BEGIN_NECESSARY" (above) is essential to works! and below definitions
      //
      prcPrivateProc(i); // works! "i" on the scope!
      //
      prcPublicProc(i); // works! "i" on the scope!
      //
      {
       if (i = 4) then // works too, with BEGIN
        break;
       }
      //
      if (i = 10) then
        ShowMessage(Format('Value to i = %d', [i])); // works! "i" on the scope!
      //
    end; // end to "BEGIN_NECESSARY"
    //
    // prcPrivateProc(i); // dont works! "i" out of scope!
    //
    // prcPublicProc(i); //  ont works! "i" out of scope!
    //
    // ShowMessage(Format('Value to i = %d', [i]));  // dont works! "i" out of scope!
    //
  end;
  //
  // prcPrivateProc(i); // dont works! "i" out of scope!
  //
  // prcPublicProc(i);  // dont works! "i" out of scope!
  //
  // ShowMessage(Format('Value to i = %d', [i]));  // dont works! "i" out of scope!
  //
end;

procedure TForm1.Button2Click(Sender: TObject);
{
  //**********
  procedure prcSub_Procedure1;
  begin
  s := s + ', i dont work in prcSub_Procedure1! See my definition is below (later)';
  end;
  //**********
}
//
var // <---
  // i: Integer;  // if defined here, will conflict with "i" defined in "var inline below"
  //
  s: String; // scope global to your procedure, same if used in sub-procedures defined here!

  lUrl: String;

  // **********
  procedure prcSub_Procedure2;
  begin
    s := s + ', im re-writed in prcSub_Procedure2! See my definition is above (before)';
  end;

// **********
begin
  //
  // DONT WORRY ABOUT "line red" in your editor screen!  HERE NONE RED-LINE APPEARS!
  //
  lUrl := 'http://www.idera.com&#39;;
  //
  ComboBox1.Items.Clear;
  //
  // begin // BEGIN_1     { uncomment here and showmessage and my procedure prcPrivate and prcPublic}
  //
  var   i := Random(20); { var "inline" only works on the "block" is defined! }
  var   ext := LowerCase(ExtractFileExt(lUrl));
  //
  begin // BEGIN_2   // its not necessary to ShowMessage or my procedure prcPrivate and prcPublic works
    //
    ComboBox1.Items.Add(Format('Value to i = %d', [i]));
    //
    ComboBox1.ItemIndex := i; // "BEGIN_NECESSARY" (above) is essential to works! and below definitions
    //
    prcPrivateProc(i); // works! "i" on the scope!
    //
    prcPublicProc(i); // works! "i" on the scope!
    //
    if (i = 10) then
      ShowMessage(Format('Value to i = %d', [i])); // works! "i" on the scope!
    //
  end; // end to BEGIN_2
  //
  prcPrivateProc(i); // works to BEGIN_1 and BEGIN_2 defined
  //
  prcPublicProc(i); // works to BEGIN_1 and BEGIN_2 defined
  //
  ShowMessage(Format('Value to i = %d', [i])); // works to BEGIN_1 and BEGIN_2 defined
  //
  // end; // end to BEGIN_1
  //
  prcPrivateProc(i); // dont works! if BEGIN_1 defined, then "i"/"ext" out of scope!
  //
  prcPublicProc(i); // dont works! if BEGIN_1 defined, then "i"/"ext" out of scope!
  //
  ShowMessage(Format('Value to i = %d', [i])); // dont works! if BEGIN_1 defined, then "i"/"ext" out of scope!
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  ShowMessage('destroyng....');
end;

procedure TForm1.prcPrivateProc(lVarA: Integer);
begin
  ShowMessage(Format('lVarA = %d', [lVarA]));
end;

procedure TForm1.prcPublicProc(lVarB: Integer);
begin
  ShowMessage(Format('lVarB = %d', [lVarB]));
end;

end.
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!
作者:
男 vkow (vkow) ▲▲▲▲▲ -
普通会员
2020/1/9 7:48:22
20楼: 目前不用的理由,就是早该加入。现在加入太晚了。

为了兼容之前的xe版本,没必要用这种语法。
----------------------------------------------
-
作者:
男 wjhyp (wjhyp) ▲△△△△ -
注册会员
2020/2/16 19:51:57
21楼: 还可以类型推断,学习了。
----------------------------------------------
-
信息
登陆以后才能回复
Copyright © 2CCC.Com 盒子论坛 v2.1 版权所有 页面执行42.96875毫秒 RSS