将 TStringList 包装在记录中

发布于 2024-07-30 02:12:43 字数 479 浏览 10 评论 0 原文

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

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


  finally
    TempList.Free;
  end;
end;

能够删除这样一个常见实用程序类的创建和释放,那就太好了。

既然我们现在有了带有方法的记录,是否可以将像 TStringList 这样的类包装在 记录一下,这样我就可以:

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


end;

I tend to use Delphi's TStringList for text manipulation, so I write a lot of procedures/functions like:

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


  finally
    TempList.Free;
  end;
end;

It would be nice to cut out the creation and freeing for such a common utility class.

Since we now have records with methods, is it possible to wrap a Class like TStringList in a
Record so I could just have:

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


end;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

面如桃花 2024-08-06 02:12:43

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

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,因此生命周期管理是自动的。 这适用于永远不会包含对自身的引用(创建循环)的对象 - 引用计数需要各种技巧来克服引用图中的循环。

It's possible. Create an interface that exposes the methods / objects you want:

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

Implement the interface, and have it wrap a real TStringList:

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

Then implement the record:

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;

The fact that there's an interface inside the record means the compiler will handle reference counting automatically, calling _AddRef and _Release as copies get created and destroyed, so lifetime management is automatic. This works for objects that will never contain a reference to themselves (creating a cycle) - reference counting needs various tricks to get over cycles in the reference graph.

翻身的咸鱼 2024-08-06 02:12:43

如果您有幸升级到 Delphi 2009,请查看 Barry 对智能指针的研究

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;

它们真的很酷,但需要泛型和匿名方法。 如果您尚未升级到 Delphi 2009,请立即升级! 特别是当他们提供 BOGO 特别时。 您还可以免费获得 Marco Delphi 开发人员手册 >下载试用版。 我也已经购买了它的副本。

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.

跨年 2024-08-06 02:12:43

还有另一个示例已在 CC 中实现

StringList 与 TStringList 相同,只是它是一个值
类型。 它不必被创建、销毁或放入
尝试/最后。 这是由编译器为您完成的。 有
实际上,这些工作没有特殊的性能损失:

<前><代码>变量
字符串:字符串列表;
astr:字符串;
开始
字符串.Add('test1');
字符串.Add('test2');
aStr := 字符串(字符串);
RichEdit.Lines.AddStrings(字符串);
结尾;

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

它已经为您提供了 TStringList 的所有内容。

There is another example already implemented in CC.

StringList is the same as TStringList except that it is a value
type. It does not have to be created, destroyed or put within
try/finally. This is done by the compiler for you. There are
virtually no special performance penalties for these to work:

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

The code can be used as a template to wrap any TObject as a value class type.

It already has everything for a TStringList exposed for you.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文