勇敢的碗豆 發表於 2022-9-14 11:45:00

Delphi 新语法:泛型

<p>  这里的新语法一般指Delphi7不支持的语法,高版本中会经常遇到,所以花一点时间学会使用它。泛型是一种特殊的类型。你不用一开始就指明参数的具体类型,而是先定义一个类型变量,在使用的时候再确定参数的具体类型。准备从万一博客中学习,节约翻找资料的时间。</p>
<h2 id="最简单的泛型">最简单的泛型</h2>
<p>一开始我们看下Tbyte类型的定义<br>
继续看一下类型TBytes是如何定义出来的.<br>
首先:<br>
<code>type TArray&lt;T&gt; = array of T;</code><br>
然后:<br>
<code>type TBytes = TArray&lt;Byte&gt;;</code><br>
TBytes为标准的字节泛型,深一步也就是字节数组.<br>
其实就相当于<code>TBytes = array of Byte;</code>Delphi7没有泛型概念,可以这么定义.</p>
<p>  首先定义一个泛型数组<code>TArr&lt;T&gt; = array of T</code>,后面声明变量的时候可以吧<code>TArr&lt;T&gt;</code>尖括号中的T换成想要的类型,可以是整形、字符串、浮点、数据结构、类等等。</p>
<pre><code class="language-pascal">implementation

{$R *.dfm}
type
TArr&lt;T&gt; = array of T; {定义一个泛型数组}
{虽然大家习惯用 T 来泛指其他类型, 但使用其他合法的标识符也是可以的。
简单来说就是粗范围的定义一个T,后面声明变量的时候可以自己修改变量类型。}

procedure TForm1.Button1Click(Sender: TObject);
var
Arr: TArr&lt;Integer&gt;;
i: Integer;
begin
for i := Low(Arr) to High(Arr) do
    Arr := i * i;

Memo1.Clear;
for i := Low(Arr) to High(Arr) do
    Memo1.Lines.Add(Format('Arr[%d] = %d', ]));
end;

procedure TForm1.Button2Click(Sender: TObject);
var
Arr: TArr&lt;string&gt;;
i: Integer;
begin
for i := Low(Arr) to High(Arr) do
    //重复某个字符3次
    Arr := StringOfChar(Char(i + 97), 3);

Memo1.Clear;
for i := Low(Arr) to High(Arr) do
    Memo1.Lines.Add(Format('Arr[%d] = %s', ]));
end;

procedure TForm1.Button3Click(Sender: TObject);
var
Arr: TArr&lt;Single&gt;;
i: Integer;
begin
for i := Low(Arr) to High(Arr) do
    Arr := 100 / (i + 1);

Memo1.Clear;
for i := Low(Arr) to High(Arr) do
    Memo1.Lines.Add(Format('Arr[%d] = %f', ]));
end;

procedure TForm1.Button4Click(Sender: TObject);
var
Arr: TArr&lt;TPoint&gt;;
i: Integer;
begin
for i := Low(Arr) to High(Arr) do
    Arr := Point(i, i * 2);

Memo1.Clear;
for i := Low(Arr) to High(Arr) do
    Memo1.Lines.Add(Format('Arr[%d] = (%d,%d)', .X, Arr.Y]));
end;

procedure TForm1.Button5Click(Sender: TObject);
var
Arr: TArr&lt;TButton&gt;;
i: Integer;
begin
for i := Low(Arr) to High(Arr) do
begin
    Arr := TButton.Create(Self);
    //合并字符串
    Arr.Name := Concat('Btn', IntToStr(i + 1));
end;

Memo1.Clear;
for i := Low(Arr) to High(Arr) do
    Memo1.Lines.Add(Format('Arr[%d] is %s', .Name]));

for i := Low(Arr) to High(Arr) do
    Arr.Free;
end;
</code></pre>
<h2 id="泛型类tlist">泛型类TList<t></t></h2>
<p>想要使用<code>TList&lt;T&gt;</code>必须先引用泛型容器单元<code>Generics.Collections</code></p>
<pre><code class="language-pascal">//引用新增的泛型容器单元
uses
Generics.Collections;

//定义一个泛型 TList 类, 这指定了要用于 string}
var
List: TList&lt;string&gt;;
str: string = 'Test';

//建立
procedure TForm1.FormCreate(Sender: TObject);
begin
List := TList&lt;string&gt;.Create;

Memo1.Clear;
Edit1.Text := str;
Button1.Caption := Button1.Caption + ' 显示';
Button2.Caption := Button2.Caption + ' 添加';
Button3.Caption := Button3.Caption + ' 插入';
Button4.Caption := Button4.Caption + ' 删除1';
Button5.Caption := Button5.Caption + ' 删除2';
Button6.Caption := Button6.Caption + ' 查找';
Button7.Caption := Button7.Caption + ' 排序';
Button8.Caption := Button8.Caption + ' 翻转';
Button9.Caption := Button9.Caption + ' 清空';
Button10.Caption := Button10.Caption + ' 添加数组';
end;

//释放
procedure TForm1.FormDestroy(Sender: TObject);
begin
List.Free;
end;

procedure TForm1.Edit1Change(Sender: TObject);
begin
if Edit1.Text &lt;&gt; '' then str := Edit1.Text;
end;

//显示
procedure TForm1.Button1Click(Sender: TObject);
var
i: Integer;
begin
Memo1.Clear;
for i := 0 to List.Count - 1 do
    Memo1.Lines.Add(List);{List = List.Item}
Text := Format('当前总数: %d', );
end;

//添加
procedure TForm1.Button2Click(Sender: TObject);
begin
List.Add(str);
Button1.Click; {刷新显示}
end;

//插入, 譬如插入在最前面
procedure TForm1.Button3Click(Sender: TObject);
begin
List.Insert(0, str);
Button1.Click;
end;

//根据序号删除, 譬如删除第一个数据
procedure TForm1.Button4Click(Sender: TObject);
begin
List.Delete(0);
Button1.Click;
end;

//根据内容删除, 譬如删除第一个数据
procedure TForm1.Button5Click(Sender: TObject);
var
s: string;
begin
s := List;
List.Remove(s);
Button1.Click;
end;

//查找
procedure TForm1.Button6Click(Sender: TObject);
var
n: Integer;
begin
n := List.IndexOf(str); {LastIndexOf 是从后面找; 也可用 List.Contains(str) 判断是否包含 str}
if n = -1 then
    ShowMessage('没找到')
else
    ShowMessageFmt('%s 是第 %d 个', );
end;

//排序
procedure TForm1.Button7Click(Sender: TObject);
begin
List.Sort;
Button1.Click;
end;

//翻转
procedure TForm1.Button8Click(Sender: TObject);
begin
List.Reverse;
Button1.Click;
end;

//清空
procedure TForm1.Button9Click(Sender: TObject);
begin
List.Clear;
Button1.Click;
end;

//添加数组
procedure TForm1.Button10Click(Sender: TObject);
const
arr: array of string = ('CodeGear', 'Delphi', '2009');
begin
List.Add('Embarcadero');
List.AddRange(arr);
Button1.Click;
end;
</code></pre>
<h2 id="泛型类tqueue">泛型类TQueue<t></t></h2>
<p>TQueue 队列类主要有三个方法、一个属性:<br>
Enqueue(入列)、Dequeue(出列)、Peek(查看下一个要出列的元素);<br>
Count(元素总数). 队列类是采用先进先出原则。</p>
<pre><code class="language-pascal">implementation

{$R *.dfm}

uses
System.Generics.Collections;

type
TRec = record
    Name: string;
    Age: Word;
end;

var
Queue: Tqueue&lt;TRec&gt;;

procedure TForm1.Button1Click(Sender: TObject);
var
rec: TRec;
begin
rec.Name := StringOfChar(Char(65 + Random(26)), 3);
rec.Age := Random(150);
Queue.Enqueue(rec);
Text := Format('当前队列成员总数: %d', );

{让 Memo1 配合显示}
Memo1.Lines.Add(Format('%s, %d', ));
end;

procedure TForm1.Button2Click(Sender: TObject);
var
rec: TRec;
begin
if Queue.Count = 0 then Exit;
rec := Queue.Dequeue;
ShowMessage(Format('%s, %d', ));
Text := Format('当前队列成员总数: %d', );

{让 Memo1 配合显示}
Memo1.Lines.Delete(0);
end;

procedure TForm1.Button3Click(Sender: TObject);
var
rec: TRec;
begin
if Queue.Count = 0 then Exit;
rec := Queue.Peek;
ShowMessage(Format('%s, %d', ));
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
Queue:= Tqueue&lt;TRec&gt;.Create();

Memo1.Clear;
Button1.Caption := Button1.Caption + ' 入列';
Button2.Caption := Button2.Caption + ' 出列';
Button3.Caption := Button3.Caption + ' 下一个出列的...';
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
Queue.Free;
end;
</code></pre>
<h2 id="泛型类tstack">泛型类TStack<t></t></h2>
<p>堆栈类与队列类相似,堆栈的出列采用的是先进后出的方式<br>
压栈采用Stack.Push(rec); 出栈采用Stack.Pop;下一个出列的依然是用Stack.Peek;</p>
<h2 id="泛型类tdictionarycardinal-string">泛型类TDictionary&lt;cardinal, string&gt;;</h2>
<p>类似字典,一个值对应着一个值,可以是数字与字符串,也可以是字符串与字符串.<br>
在字典场景下使用该泛型极为方便.</p>
<pre><code class="language-pascal">uses
System.Generics.Collections;

var
Dictionary: TDictionary&lt;cardinal, string&gt;;
procedure TForm1.Button1Click(Sender: TObject);
var
key: Cardinal;
value: string;
str: string;
k,v: Boolean;
begin
key := StrToIntDef(Edit1.Text, 0);
value := Edit2.Text;
if value = '' then value := 'Null';

k := Dictionary.ContainsKey(key);   {Key 是否存在}
v := Dictionary.ContainsValue(value); {Value 是否存在}

if not k then
begin
    Dictionary.Add(key, value);
    Memo1.Lines.Add(Format('%d=%s', )); {同步显示}
end;

if k and not v then
begin
    str := Format('key 已存在: %d=%s; 是否修改其值?', ]);
    if MessageBox(0, PChar(str), '提示', MB_OKCANCEL or MB_ICONQUESTION) = mrOk then
    begin
      //Dictionary := value; {Dictionary = Dictionary.Item}
      Dictionary.AddOrSetValue(key, value);       {也可使用上一句}
      Memo1.Lines.Values := value; {同步显示}
    end;
end;

if k and v then
begin
    str := Format('%d=%s 已存在, 不能重复添加', );
    MessageBox(0, PChar(str), '错误', MB_OK + MB_ICONHAND);
end;

Text := IntToStr(Dictionary.Count);
end;

procedure TForm1.Button2Click(Sender: TObject);
var
key: Integer;
i: Integer;
begin
key := StrToIntDef(Edit1.Text, 0);

if not Dictionary.ContainsKey(key) then
begin
    ShowMessageFmt('key: %d 不存在', );
    Exit;
end;

Dictionary.Remove(key);
Text := IntToStr(Dictionary.Count);

{同步显示}
i := Memo1.Lines.IndexOfName(IntToStr(key));
if i &gt; -1 then Memo1.Lines.Delete(i);
end;

procedure TForm1.Button3Click(Sender: TObject);
var
key: Integer;
value: string;
begin
key := StrToIntDef(Edit1.Text, 0);
if Dictionary.TryGetValue(key, value) then
    ShowMessageFmt('key: %d 已存在, 其值是: %s', )
else
    ShowMessageFmt('key: %d 不存在', )
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
Dictionary.Clear;
Text := IntToStr(Dictionary.Count);
Memo1.Clear; {同步显示}
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
Dictionary:=TDictionary&lt;cardinal, string&gt;.Create;
Memo1.Clear;
Button1.Caption := Button1.Caption + ' 添加';
Button2.Caption := Button2.Caption + ' 删除';
Button3.Caption := Button3.Caption + ' 尝试取值';
Button4.Caption := Button4.Caption + ' 清空';

Edit1.Clear;
Edit2.Clear;
Edit1.NumbersOnly := True;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
Dictionary.Free;
end;
</code></pre>


</div>
<div id="MySignature" role="contentinfo">
    <!--打赏-->
<br/>
<br/>
<br/>
<div class="reward">
    <div class="reward-button">赏
      <span class="reward-code">
            <span class="wechat-code"> <img class="wechat-img wdp-appear" src="https://blog-static.cnblogs.com/files/YXGust/weixin.gif"><b>微信打赏</b> </span>
            <span class="alipay-code"> <img class="alipay-img wdp-appear" src="https://blog-static.cnblogs.com/files/YXGust/zfb.gif"><b>支付宝打赏</b> </span>
      </span>
    </div>
    <br/>
    <p class="reward-notice">如果觉得文章对您有用,请随意打赏。您的支持将鼓励我继续创作!</p>
</div>
<!--打赏-->

<!--签名-->
<div id="MySignature" role="contentinfo">
<p style="padding: 10px 10px 10px 10px; border: 1px dashed #009688; font-family: 幼圆; front-size: 16px;">
作者:YXGust
<br/>
出处:https://www.cnblogs.com/YXGust/p/16647561.html
<br/>
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
<br/>
本博文版权归本博主所有,转载请注明原文链接
<br/>
</p>
</div>
<!--签名--><br><br>
来源:https://www.cnblogs.com/YXGust/p/16647561.html
頁: [1]
查看完整版本: Delphi 新语法:泛型