一、指定 Owner 后, 随 Owner 连带释放:
//uses Vcl.StdCtrls, Vcl.ExtCtrls; var panel: TPanel; procedure TForm1.Button1Click(Sender: TObject); begin panel := TPanel.Create(Self); panel.Parent := Self; with TButton.Create(panel) do //AOwner = panel begin Parent := panel; Caption := 'New Button'; end; end; procedure TForm1.Button2Click(Sender: TObject); begin if Assigned(panel) then FreeAndNil(panel); //连带释放以它为 Owner 的对象 end;
二、使用接口:
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) Button1: TButton; procedure Button1Click(Sender: TObject); end; // IBass = Interface function GetName: string; procedure SetName(const AName: string); property Name: string read GetName write SetName; end; // TBass = class(TInterfacedObject, IBass) private FName: string; protected function GetName: string; procedure SetName(const AName: string); public constructor Create(const AName: string); end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); var X: IBass; begin X := TBass.Create('WanYi'); ShowMessage(X.Name); X.Name := '万一'; ShowMessage(X.Name); {X 在此自动释放} end; { TBass } constructor TBass.Create(const AName: string); begin FName := AName; end; function TBass.GetName: string; begin Result := FName; end; procedure TBass.SetName(const AName: string); begin FName := AName; end; end.
三、使用结构:
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) Button1: TButton; procedure Button1Click(Sender: TObject); end; // TBass = record private FName: string; procedure SetName(const AName: string); public constructor Create(const AName: string); property Name: string read FName write SetName; end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); var X: TBass; begin X := TBass.Create('WanYi'); ShowMessage(X.Name); X.Name := '万一'; ShowMessage(X.Name); {X 在此自动释放} end; { TBass } constructor TBass.Create(const AName: string); begin FName := AName; end; procedure TBass.SetName(const AName: string); begin FName := AName; end; end.
四、在 initialization 中建立、在 finalization 中释放:
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) Button1: TButton; procedure Button1Click(Sender: TObject); end; var Form1: TForm1; implementation {$R *.dfm} var List: TStringList; procedure TForm1.Button1Click(Sender: TObject); begin List.Clear; List.Add('WanYi'); ShowMessage(List.Text); end; initialization List := TStringList.Create; finalization List.Free; end.
五、使用动态数组而不是 TList、TStringList 等:
procedure TForm1.Button1Click(Sender: TObject); var arr: Array of string; i: Integer; s: string; begin for i := 0 to 6 do begin SetLength(arr, Length(arr)+1); arr[High(arr)] := StringOfChar(Char(i+65), 3); end; for s in arr do ShowMessage(s); end; procedure TForm1.Button2Click(Sender: TObject); var arr: TArray<string>; i: Integer; s: string; begin for i := 0 to 6 do begin SetLength(arr, Length(arr)+1); arr[High(arr)] := StringOfChar(Char(i+65), 3); end; for s in arr do ShowMessage(s); end;
六、使用 TObjectList 而不是 TList:
uses System.Contnrs; procedure TForm1.Button1Click(Sender: TObject); var list: TObjectList; i: Integer; btn: TButton; begin list := TObjectList.Create; for i := 0 to 6 do begin btn := TButton.Create(Self); with btn do begin Caption := Format('Btn %d', [i+1]); Parent := Self; Top := Height * i; Left := Width * i div 2; end; list.Add(btn); end; ShowMessage('TObjectList 释放时, 会同时释放其中的对象'); list.Free; end; procedure TForm1.Button2Click(Sender: TObject); var list: TList; i: Integer; btn: TButton; begin list := TList.Create; for i := 0 to 6 do begin btn := TButton.Create(Self); with btn do begin Caption := Format('Btn %d', [i+1]); Parent := Self; Top := Height * i; Left := Width * i div 2; end; list.Add(btn); end; ShowMessage('TList 释放后, 其中的对象并未释放'); list.Free; end;
七、使用 TObjectList<T> 而不是 TList<T>:
uses System.Generics.Collections; procedure TForm1.Button1Click(Sender: TObject); var list: TObjectList<TButton>; i: Integer; btn: TButton; begin list := TObjectList<TButton>.Create; for i := 0 to 6 do begin btn := TButton.Create(Self); with btn do begin Caption := Format('Btn %d', [i+1]); Parent := Self; Top := Height * i; Left := Width * i div 2; end; list.Add(btn); end; ShowMessage('TObjectList 释放时, 会同时释放其中的对象'); list.Free; end; procedure TForm1.Button2Click(Sender: TObject); var list: TList<TButton>; i: Integer; btn: TButton; begin list := TList<TButton>.Create; for i := 0 to 6 do begin btn := TButton.Create(Self); with btn do begin Caption := Format('Btn %d', [i+1]); Parent := Self; Top := Height * i; Left := Width * i div 2; end; list.Add(btn); end; ShowMessage('TList 释放后, 其中的对象并未释放'); list.Free; end;
八、使用结构体而不是结构体指针:
{假如某个函数的参数需要一个结构指针} function Area(rect: PRect): Integer; begin Result := rect.Width * rect.Height; // Result := rect^.Width * rect^.Height; end; {直接声明指针并分配空间后需手动释放} procedure TForm1.Button1Click(Sender: TObject); var P: PRect; begin New(P); P^ := Rect(10, 10, 60, 50); ShowMessage(IntToStr(Area(P))); //2000 Dispose(P); end; {} procedure TForm1.Button2Click(Sender: TObject); var R: TRect; begin R := Rect(10, 10, 60, 50); ShowMessage(IntToStr(Area(@R))); //2000 end;