从 TObjectList 中提取对象

发布于 2024-07-08 14:26:01 字数 349 浏览 11 评论 0原文

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

Extract 方法是唯一的选择吗?

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

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

ExtractedObject := TheList.Extract(Idx);

... 不存在。

I have a TObjectList with OwnsObjects = true. It contains quite a few objects. Now I want to remove the object at index Idx from that list, without freeing it.

Is the Extract method the only option?

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

All other methods seem to free the object. I am looking for something a little bit more efficient, that does not do a linear search every time, since I already know the index of the object. Something like an overloaded ...

ExtractedObject := TheList.Extract(Idx);

... which does not exist.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

梦与时光遇 2024-07-15 14:26:01

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

Why not just set OwnsObjects to false, do your removal, then set it to true again?

梦忆晨望 2024-07-15 14:26:01

这就是类助手的用处,

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);

This is where class helpers can be usefull

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;

You can now use:

MyObjList.ExtractByIndex(MyIndex);
风蛊 2024-07-15 14:26:01

如果您查看删除的代码,就会发现是通知方法导致释放发生。

这应该有效:

  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;

If you look at the code for delete, it's the notify method which causes the freeing to happen.

This should work :

  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;
云淡风轻 2024-07-15 14:26:01

建议的辅助类(由 Gamecat)将导致 Thomas 希望摆脱的相同查找。

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

我会建议像这样的东西:

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

这将为您提供对象,就像 Extract() 所做的那样,然后从列表中删除它,而不进行任何查找。 现在,您可以将其放入某个方法中,例如辅助类或子类或您喜欢的任何地方。

The proposed helperclass (by Gamecat) will result in the same lookup that Thomas would like to get rid of.

If you take a look at the source, you can see what Extract() really does, and then use the same approach.

I will suggest something like tis:

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

This will give you the object, as Extract() does, and then delete it from the list, without any lookups. Now you can put this in a method some where, a helperclass or subclass or wher ever you like.

二手情话 2024-07-15 14:26:01

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

I don't use Delphi/C++Builder some time ago, but as far as I can renmember thats the only way.
My suggestion is to use a TList instead, and manually delete the objects when required.

十年不长 2024-07-15 14:26:01

有什么问题吗:

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

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

Anything wrong with:

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

There is time needed for the create and assign but not for the search of the list. Efficiency depends on the size of the object -v- the size of the list.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文