Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wrapping TStringList in a Record

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;
like image 488
HMcG Avatar asked Nov 30 '22 19:11

HMcG


2 Answers

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.

like image 114
Barry Kelly Avatar answered Dec 09 '22 14:12

Barry Kelly


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.

like image 32
Jim McKeeth Avatar answered Dec 09 '22 13:12

Jim McKeeth