4

我倾向于使用 Delphi 的 TStringList 进行文本操作,所以我编写了很多程序/函数,例如:

var
  TempList: TStringList;
begin
  TempList:= TStringList.Create;
  try
    // blah blah blah do stuff with TempList   


  finally
    TempList.Free;
  end;
end;

为这样一个常见的实用程序类取消创建和释放会很好。

由于我们现在有带有方法的记录,是否可以将像 TStringList 这样的类包装在 Record 中,这样我就可以拥有:

var
  TempList: TRecordStringList;
begin
  // blah blah blah do stuff with TempList   


end;
4

3 回答 3

15

这是可能的。创建一个公开所需方法/对象的接口:

type
  IStringList = interface
    procedure Add(const s: string); // etc.
    property StringList: TStringList read GetStringList; // etc.
  end;

实现接口,并让它包装一个真实的TStringList

type
  TStringListImpl = class(TInterfacedObject, IStringList)
  private
    FStringList: TStringList; // create in constructor, destroy in destructor
    // implementation etc.
  end;

然后实现记录:

type
  TStringListRecord = record
  private
    FImpl: IStringList;
    function GetImpl: IStringList; // creates TStringListImpl if FImpl is nil
                                   // returns value of FImpl otherwise
  public
    procedure Add(const s: string); // forward to GetImpl.Add
    property StringList: TStringList read GetStringList; // forward to
                                                         // GetImpl.StringList
    // etc.
  end;

记录中存在接口这一事实意味着编译器将自动处理引用计数,在创建和销毁副本时调用 _AddRef 和 _Release,因此生命周期管理是自动的。这适用于永远不会包含对自身的引用(创建循环)的对象 - 引用计数需要各种技巧来克服引用图中的循环。

于 2009-08-01T15:44:47.520 回答
4

If you are lucky enough to have upgraded to Delphi 2009 then check out Barry's work with smart pointers.

TSmartPointer<T: class> = record
strict private
  FValue: T;
  FLifetime: IInterface;
public
  constructor Create(const AValue: T); overload;
  class operator Implicit(const AValue: T): TSmartPointer<T>;
  property Value: T read FValue;
end;

They are really cool, but require Generics and Anonymous methods. If you haven't upgraded to Delphi 2009, then do it now! Especially while they are offering their BOGO special. You also get Marco's Delphi Developer Handbook free just for downloading the trial. I already purchased a copy of it too.

于 2009-08-01T19:37:43.433 回答
2

CC 中已经实现了另一个示例。

StringList 与 TStringList 相同,只是它是一个值类型。它不必被创建、销毁或放在 try/finally 中。这是由编译器为您完成的。这些工作几乎没有特殊的性能损失:

var 
  strings: StringList;
  astr: string;
begin
  strings.Add('test1');
  strings.Add('test2');
  aStr := string(strings);
  RichEdit.Lines.AddStrings(strings);
end;

该代码可用作模板,将任何 TObject 包装为值类类型。

It already has everything for a TStringList exposed for you.

于 2009-08-01T19:33:26.170 回答