ZigiZ
ZigiZ

Reputation: 2520

How to create a TStringList descendant with Owner that will auto free the TStringList?

I'm hoping to create something like a "TOwnedStringList" (class name is a fiction) that I could construct as:

sl := TOwnedStringList.Create(Self);
sl.Sorted := True;
sl.Duplicates := dupIgnore; 
sl.Add(...);
// etc...

Where Self could be a Form (for example), so that the Owner will auto free the StringList. I want to be able to avoid calling sl.Free myself.

Is This possible?

Upvotes: 9

Views: 692

Answers (1)

David Heffernan
David Heffernan

Reputation: 613322

That's going to be a little messy. You'd need to do something like this.

type
  TOwnerComponent = class(TComponent)
  private
    FOwnedObject: TObject;
  public
    constructor Create(Owner: TComponent; OwnedObject: TObject);
    destructor Destroy; override;
  end;

  TOwnedStringList = class(TStringList)
  private
    FOwner: TOwnerComponent;
  public
    constructor Create(Owner: TComponent);
    destructor Destroy; override;
  end;

{ TOwnerComponent }

constructor TOwnerComponent.Create(Owner: TComponent; OwnedObject: TObject);
begin
  inherited Create(Owner);
  FOwnedObject := OwnedObject;
end;

destructor TOwnerComponent.Destroy;
begin
  FOwnedObject.Free;
  inherited;
end;

{ TOwnedStringList }

constructor TOwnedStringList.Create(Owner: TComponent);
begin
  inherited Create;
  if Assigned(Owner) then
    FOwner := TOwnerComponent.Create(Owner, Self);
end;

destructor TOwnedStringList.Destroy;
begin
  if Assigned(FOwner) and not (csDestroying in FOwner.ComponentState) then
  begin
    FOwner.FOwnedObject := nil;
    FOwner.Free;
  end;
  inherited;
end;

Basically you create an instance of TOwnerComponent that is owned by the Owner that you pass to TOwnedStringList.Create. When that Owner dies, it destroys the TOwnerComponent which in turn destroys your string list.

The code is resilient to an explicit Free being called on the string list.

Upvotes: 14

Related Questions