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

1

9

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?

Issue answered 4/3, 2013 at 12:41 Comment(0)
G
14

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.

Grantor answered 4/3, 2013 at 12:54 Comment(3)
Looks promising. Should the TOwnerComponent constructor be created with reintroduce directive? Also, How can I protect the TOwnedStringList against sl.Create(nil) and explicit sl.Free?Issue
Create(nil) is fine. That just means, no owner, let me take charge of ownership. Or if you don't want that, then raise an exception. Explicit Free will take a little more thinking about. Bear with me.Grantor
How about if Assigned(FOwner) and not (csDestroying in FOwner.ComponentState)?Issue

© 2022 - 2024 — McMap. All rights reserved.