首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> Delphi

Delphi 2009 TStringBuilder 進階:Equals 方法與物件身分識別機制

     編輯:Delphi

Equals:內容相等 vs 參考相等

TStringBuilder.Equals 用於判斷兩個 StringBuilder 實例的內容是否相同,而非參考相等。這與 .NET StringBuilder.Equals 行為一致:比較緩衝區實際字元內容。

核心 API

方法參數回傳說明
Equalsobj: TObjectBoolean比較內容相等性 (覆寫 TObject.Equals)

完整實作程式碼


procedure TForm1.Button1Click(Sender: TObject); // 內容比較
var
  sb1, sb2: TStringBuilder;
  b: Boolean;
begin
  sb1 := TStringBuilder.Create('abc');
  sb2 := TStringBuilder.Create('abc');
  try
    b := sb1.Equals(sb2); // True - 內容相同
    ShowMessage(BoolToStr(b, True));

    sb2.Length := 0; // 清空 sb2
    b := sb1.Equals(sb2); // False - 內容不同
    ShowMessage(BoolToStr(b, True));
  finally
    sb1.Free;
    sb2.Free;
  end;
end;

procedure TForm1.Button2Click(Sender: TObject); // 參考行為示範
var
  sb1, sb2: TStringBuilder;
begin
  sb1 := TStringBuilder.Create('abc');
  try
    sb2 := sb1; // sb2 指向同一實例 (參考複製)

    sb1.Append('123');
    ShowMessage(sb2.ToString); // 'abc123' - sb2 看到變更

    sb2 := sb1.Replace('123', ' 123'); // Replace 回傳自我參考
    ShowMessage(sb1.ToString); // 'abc 123'
    ShowMessage(sb2.ToString); // 'abc 123' - 同一實例

    ShowMessage(BoolToStr(sb2.Equals(sb1), True)); // True - 同一實例必相等
  finally
    sb1.Free; // sb2 同一實例,勿重複 Free
  end;
end;

關鍵概念釐清

1. 內容相等 vs 參考相等

比較方式程式碼比較對象結果
內容相等sb1.Equals(sb2)緩衝區字元序列內容相同則 True
參考相等sb1 = sb2物件記憶體位址同一實例則 True
介面比較IInterface(sb1) = IInterface(sb2)介面指標同一實例則 True

2. TStringBuilder 的可變性與參考共享

  • TStringBuilder 是類別 (Class),屬參考型別
  • sb2 := sb1 只是複製參考,指向同一緩衝區
  • 任何透過 sb1 或 sb2 的修改 (Append/Replace/Insert/Remove) 都會影響同一實例
  • Replace 等修改方法回傳 Self,方便鏈式呼叫:sb.Append('a').Replace('a','b')

3. Equals 實作邏輯 (簡化版)


function TStringBuilder.Equals(obj: TObject): Boolean;
var other: TStringBuilder;
begin
  if not (obj is TStringBuilder) then Exit(False);
  other := TStringBuilder(obj);
  if Self = other then Exit(True); // 同一實例快速返回
  if Length <> other.Length then Exit(False);
  // 逐字元比較緩衝區內容
  Result := CompareMem(Pointer(FData), Pointer(other.FData), Length * SizeOf(Char));
end;

實務應用場景

1. 快取鍵值比較:以內容為鍵


type
  TCacheKey = record
    SB: TStringBuilder;
  end;

function CacheKeyEquals(const K1, K2: TCacheKey): Boolean;
begin
  Result := K1.SB.Equals(K2.SB); // 內容相同視為同一鍵
end;

2. 避免重複建構相同內容


var
  Cache: TDictionary; // 需自訂比較器

function GetOrBuildData(const Template: string): TData;
var
  key: TStringBuilder;
  existing: TStringBuilder;
begin
  key := TStringBuilder.Create(Template);
  try
    // 需實作 IEqualityComparer 使用 Equals
    if Cache.TryGetValue(key, Result) then Exit;
    Result := BuildData(Template);
    Cache.Add(key, Result); // key 內容作為鍵
  finally
    key.Free;
  end;
end;

3. 除錯/測試驗證:確認操作結果


procedure TestStringBuilderOperations;
var sb1, sb2: TStringBuilder;
begin
  sb1 := TStringBuilder.Create;
  sb2 := TStringBuilder.Create;
  try
    sb1.Append('Hello').Append(' ').Append('World');
    sb2.Append('Hello World');
    Assert(sb1.Equals(sb2), '鏈式 Append 應等同單次 Append');

    sb1.Clear.Append('Test');
    sb2.Clear.Append('Test');
    Assert(sb1.Equals(sb2), 'Clear 後相同內容應相等');
  finally
    sb1.Free; sb2.Free;
  end;
end;

常見誤區與避坑

誤區正確認知程式碼示範
Equals 比較參考比較內容sb1.Equals(sb2) ≠ (sb1 = sb2)
Replace 產生新實例修改原實例並回傳 Selfsb2 := sb1.Replace(...) → sb2 = sb1
sb2 := sb1 後 Free 兩次同一實例只能 Free 一次sb1.Free; // sb2 不可再 Free
Equals(nil) 會崩潰內部檢查 is TStringBuilder 會回傳 Falsesb1.Equals(nil) → False

效能考量

  • Equals 為 O(n):需逐字元比較,長字串較耗時
  • 長度優先檢查:長度不同立即返回 False,避免內容比較
  • 同一實例快速路徑:Self = other 直接返回 True
  • 大量比較場景:考慮預計算雜湊值 (GetHashCode) 配合字典使用

總結

TStringBuilder.Equals 實作內容語意相等,區別於參考相等。理解可變參考型別特性:sb2 := sb1 共享實例,修改方法回傳 Self 方便鏈式呼叫。善用 Equals 進行內容驗證、快取鍵值比較、測試斷言,避免參考共享導致的邏輯錯誤 (如重複 Free)。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved