分析 TStringList 存取對象的特點 – 還是回複 Test1234 的問題

來源:互聯網
上載者:User
問題來源: http://www.cnblogs.com/del/archive/2008/04/26/973346.html#1171927
在 Delphi 中儲存系列對象, 大家常用 TList 類; 有了 TObjectList(在 Contnrs 單元)以後, 儲存物件就有了更好的選擇, 因為從 TObjectList 列表中移除的對象同時會得到釋放.

很少有人使用 TStringList 儲存對象, 殊不知用 TStringList 儲存對象也有 TList 和 TObjectList 所不及的優勢.

我想在繼續探討前先重複一個概念: 對象的 "指標" 和 "首地址":
我們通過對象的指標可以找到對象, 也就是說指標是指向了對象; 對象也不過是一系列資料, "指標" 一般是指向這組資料的 "首地址".
下面代碼可以擷取 Button1 對象的 "指標" 和 "首地址":

procedure TForm1.Button1Click(Sender: TObject);begin  ShowMessageFmt('指標: %d', [Integer(@Button1)]);  {14910416}  ShowMessageFmt('首地址: %d', [Integer(Button1)]); {15011440}end;

我們再看下 TList、TObjectList 和 TStringList 添加對象的方法聲明:

TList       : function Add(Item: Pointer): Integer;TObjectList : function Add(AObject: TObject): Integer;TStringList : function AddObject(const S: string; AObject: TObject): Integer;

可以看出, TList 添加的只是指標; TObjectList 和 TStringList 添加的類型是對象.
添加對象時, 是把整個對象的資料都添加進去嗎? 當然不是, 只要記住對象的首地址就可以了(應該也是用類似指標的辦法, 我沒仔細研究), 測試代碼:

procedure TForm1.Button1Click(Sender: TObject);var  List: TStringList;begin  ShowMessageFmt('指標: %d', [Integer(@Button1)]);  {14910416}  ShowMessageFmt('首地址: %d', [Integer(Button1)]); {15011440}  List := TStringList.Create;  List.AddObject('btn', Button1);  ShowMessageFmt('取出: %d', [Integer(List.Objects[0])]); {15011440, 可以看出相同與上面的首地址}  List.Free;end;

通過 TStringList 的 AddObject 和 InsertObject 方法可以添加對象;
用 Objects[] 屬性取出對象; 用 List[] 取出字串. 樣本:

procedure TForm1.Button1Click(Sender: TObject);var  List: TStringList;  obj: TObject;  str: string;begin  List := TStringList.Create;  List.AddObject('btn', Button1);    {添加}  obj := List.Objects[0];            {取出對象}  str := List[0];                    {取出字串}  {使用對象, 有個前提:我們知道它屬於 TButton}  ShowMessage(TButton(obj).Caption); {Button1}  ShowMessage(str);                  {btn}  List.Free;end;

添加對象的指標可以嗎? 可以, 但需要轉換成無類型指標, 例:

procedure TForm1.Button1Click(Sender: TObject);var  List: TStringList;  obj: TObject;begin  List := TStringList.Create;  List.AddObject('btn', Pointer(@Button1));  List.AddObject('btn', Pointer(Button1)); {這樣也可以}  obj := List.Objects[0];  ShowMessage(TButton(obj).Caption); {顯示: Button1}  List.Free;end;

既然也可以添加指標, 那我們也可以添加不屬於 TObject 的結構等其他指標;
假如不能添加指標, 也將無法添加結構, 因為結構不屬於 TObject. 舉例:

type  PMyRec = ^TMyrec;  TMyRec = record    s: string;    i: Integer;  end;procedure TForm1.Button1Click(Sender: TObject);var  List: TStringList;  R1,R2: TMyRec;begin  List := TStringList.Create;  R1.s := 'abc';  R1.i := 123;  List.AddObject('rec', Pointer(@R1));   //List.AddObject('rec', @R1); {結構比較特殊, 不轉無類型指標也可以}  R2 := PMyRec(List.Objects[0])^;  ShowMessageFmt('%s,%d', [R2.s, R2.i]); {abc,123}  List.Free;end;

前面說到 TStringList 還會有點優勢; 首先得承認它的劣勢, 因為它是兩組資料構成的列表, 在資料量特別大的時候效率上會有劣勢; 現在說說它的優勢:
從 TList 和 TObjectList 取出的物件類型是未知的(當然作者知道), 所以一般只能儲存單一類型的對象;
因為 TStringList 有兩個欄位, 我們可以用那個 String 欄位來儲存物件類型, 從而讓 TStringList 可以同時儲存更多類型的對象. 舉例:

unit Unit1;interfaceuses  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  Dialogs, StdCtrls;type  TForm1 = class(TForm)    Button1: TButton;    procedure Button1Click(Sender: TObject);  end;var  Form1: TForm1;implementation{$R *.dfm}type  PMyRec = ^TMyrec;  TMyRec = record    s: string;    i: Integer;  end;procedure TForm1.Button1Click(Sender: TObject);var  List: TStringList;  R1,R2: TMyRec;  str: string;  i: Integer;begin  List := TStringList.Create;  R1.s := 'abc';  R1.i := 123;  str := '我是字串';  List.AddObject('1', @R1);           {用 1 表示結構 TMyRec}  List.AddObject('2', Sender);        {用 2 表示 TButton}  List.AddObject('3', Self);          {用 3 表示 TForm1}  List.AddObject('4', Pointer(str));  {用 4 表示 String}  for i := 0 to List.Count - 1 do  begin    case StrToIntDef(List[i], 0) of      1: begin           R2 := PMyRec(List.Objects[i])^;           ShowMessageFmt('%s,%d', [R2.s, R2.i]);       {abc,123}         end;      2: ShowMessage(TButton(List.Objects[i]).Caption); {Button1}      3: ShowMessage(TForm1(List.Objects[i]).Text);     {Form1}      4: ShowMessage(PChar(List.Objects[i]));           {我是字串}    end;  end;  List.Free;end;end.

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.