Search code examples
delphidelphi-7

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?


Solution

  • 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.