如何创建一个带有Owner属性的TStringList子类,以便自动释放TStringList?

9
我希望创建一个类似于“TOwnedStringList”(类名是虚构的)的东西,可以按以下方式构建:
sl := TOwnedStringList.Create(Self);
sl.Sorted := True;
sl.Duplicates := dupIgnore; 
sl.Add(...);
// etc...

Self可以是一个表单等,这样所有者将自动释放StringList。我想避免自己调用sl.Free,这可行吗?

1个回答

14

这可能会有点混乱。你需要像这样做。

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;

基本上,您需要创建一个TOwnerComponent实例,该实例由传递给TOwnedStringList.CreateOwner拥有。当该Owner失效时,它将销毁TOwnerComponent,进而销毁您的字符串列表。

代码可以抵御对字符串列表进行显式Free的调用。


1
看起来很有前途。TOwnerComponent构造函数应该使用reintroduce指令创建吗?另外,我如何保护TOwnedStringList免受sl.Create(nil)和显式的sl.Free的影响? - ZigiZ
1
Create(nil) 就可以了。这意味着没有 owner,让我来负责所有权。或者如果你不想这样,那就抛出一个异常。显式的 Free 需要再考虑一下。请耐心等待。 - David Heffernan
3
如果 FOwner 被分配了,并且 FOwner.ComponentState 不包含 csDestroying,则怎么样? - ZigiZ

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接