Delphi 从TObjectList中提取对象

Delphi 从TObjectList中提取对象,delphi,tobjectlist,tlist,Delphi,Tobjectlist,Tlist,我有一个TObjectList,OwnsObjects=true。它包含相当多的对象。现在我想从列表中删除索引Idx处的对象,而不释放它 提取方法是唯一的选择吗 ExtractedObject:=TheList.Extract(TheList[Idx]) 所有其他方法似乎都可以释放对象。我正在寻找一种更高效的方法,它不会每次都进行线性搜索,因为我已经知道对象的索引。有点像超载的 ExtractedObject:=list.Extract(Idx) 。。。这是不存在的。我不久前没有使用Delphi

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

提取方法是唯一的选择吗

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

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

ExtractedObject:=list.Extract(Idx)


。。。这是不存在的。

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

为什么不将OwnsObjects设置为false,执行删除操作,然后再次将其设置为true?

如果查看删除代码,则是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;

这是课堂助手可以发挥作用的地方

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;
建议的helperclass(由Gamecat提供)将产生Thomas希望摆脱的相同查找

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

我会建议一些类似tis的建议:

obj := list[idx];
list.list^[idx] := nil;  //<- changed from list[idx] := nil;
list.delete(idx);
obj:=list[idx];
list.list^[idx]:=nil// 有什么问题吗

ExtractedObject:=TExtractedObject.Create
ExtractedObject.Assign(列表[Idx])
删除列表(idx)


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

不幸的是,这仍然会在原始提取函数中进行线性搜索,即使我已经将对象的索引传递给了新的提取函数。但是我想将它与OwnsObjects=False/True结合起来应该可以达到目的。不幸的是,这也不起作用,因为将NIL指定给一个项会自动释放它。Oops。我完全忽略了这一点,但TList允许您通过公共属性列表PPoinerList直接访问linkedlist。将list[idx]:=nil更改为list.list^[i]:=nil;解决方案应该是合理的。这种方法要求对象从TPersistent下降,并正确地实现赋值方法
obj := list[idx];
list.list^[idx] := nil;  //<- changed from list[idx] := nil;
list.delete(idx);