2

我有一个 OwnsObjects = true 的 TObjectList。它包含相当多的对象。现在我想从该列表中删除索引 Idx 处的对象,而不释放它。

提取方法是唯一的选择吗?

ExtractedObject := TheList.Extract(TheList[Idx]);

所有其他方法似乎都释放了该对象。我正在寻找更高效的东西,它不会每次都进行线性搜索,因为我已经知道对象的索引。有点像超载...

ExtractedObject := TheList.Extract(Idx);

...不存在的。

4

6 回答 6

9

为什么不直接将 OwnsObjects 设置为 false,进行删除,然后再次将其设置为 true?

于 2008-11-12T13:57:43.273 回答
1

如果您查看删除代码,它是导致释放发生的 notify 方法。

这应该工作:

  TMyObjectList = Class(TObjectList)
  private
    fNotify: Boolean;
    { Private declarations }
    procedure EnableNotification;
    procedure DisableNotification;
  protected
    procedure Notify(Ptr: Pointer; Action: TListNotification); override;
  public
    constructor Create(AOwnsObjects: Boolean);overload;
    constructor Create; overload;
    function Extract(const idx : Integer) : TObject;
  end;


constructor TMyObjectList.Create(AOwnsObjects: Boolean);
begin
  inherited Create(AOwnsObjects);
  fNotify := True;
end;

constructor TMyObjectList.Create;
begin
  inherited Create;
  fNotify := True;
end;

procedure TMyObjectList.DisableNotification;
begin
  fnotify := False;
end;

procedure TMyObjectList.EnableNotification;
begin
  fNotify := True;
end;

function TMyObjectList.Extract(const idx: Integer) : TObject;
begin
  Result := Items[idx];
  DisableNotification;
  try
    Delete(idx);
  finally
    EnableNotification;
  end;
end;

procedure TMyObjectList.Notify(Ptr: Pointer; Action: TListNotification);
begin
 if fNotify then
   inherited;
end;
于 2008-11-12T14:45:58.513 回答
1

这是类助手可以派上用场的地方

TObjectListHelper = class helper for TObjectList
  function ExtractByIndex(const AIndex: Integer): TObject;
end;

function TObjectListHelper.ExtractByIndex(const AIndex: Integer): TObject;
begin
  Result := Items[AIndex];
 if Result<>nil then
   Extract(Result);
end;

您现在可以使用:

MyObjList.ExtractByIndex(MyIndex);
于 2008-11-12T15:12:45.463 回答
1

提议的帮助类(由 Gamecat 提出)将导致 Thomas 想要摆脱的相同查找。

如果您查看源代码,您可以看到 Extract() 的真正作用,然后使用相同的方法。

我会建议类似 tis:

obj := list[idx];
list.list^[idx] := nil;  //<- changed from list[idx] := nil;
list.delete(idx);

这将为您提供对象,就像 Extract() 所做的那样,然后将其从列表中删除,无需任何查找。现在你可以把它放在一个方法中,一个助手类或子类或者你喜欢的任何地方。

于 2008-11-12T21:05:43.787 回答
0

我前段时间不使用 Delphi/C++Builder,但据我所知,这是唯一的方法。我的建议是改用 TList,并在需要时手动删除对象。

于 2008-11-12T13:45:08.963 回答
0

有什么问题:

ExtractedObject := TExtractedObject.Create;
ExtractedObject.Assign(Thelist[Idx]);
TheList.Delete(idx);

创建和分配需要时间,但搜索列表不需要时间。效率取决于对象的大小 -v- 列表的大小。

于 2008-11-13T20:13:15.663 回答