var
List: TObjectList<TNewObject>;
Obj: TNewObject;
begin
Obj := TNewObject.Create('Three');
List := TObjectList<TNewObject>.Create();
List.Add(TNewObject.Create('One'));
List.Add(Obj);
Obj.free; //手动释放
List.Pack(function(const L, R: TNewObject): Boolean begin result:= L = nil; end) //如何判断L是否释放

List.Free
readln;
end.代码如上。
本来TObjectList提供删除其中的元素后,自动释放被删除的元素。
但是这个元素一旦在外部被删除,那么List.Free的时候,就会报错。
因此,需要对List进行清理,即Pack,清除为空的元素。
于是就需要在Pack中,定义出什么样的元素是空元素,涉及到对L的判断。
if L = nil then ...
if Not Boolean(L) then ...
if Assigned(L) then ...
这三种办法,都无法判断Obj被Free掉了
求高人指点!

解决方案 »

  1.   

    可以List.OwnsObjects := false;
      

  2.   


    假如一定要用List.OwnsObjects := True; 这种,该怎么判断其中的Obj是不是被Free掉了?
      

  3.   


    假如一定要用List.OwnsObjects := True; 这种,该怎么判断其中的Obj是不是被Free掉了?可以为TNewObject类型写一个helper,替换free方法,在里面检查List。不过从设计角度来说。这是一种非常糟糕的设计,强行关联外部对象,增加了耦合度。
      

  4.   


    假如一定要用List.OwnsObjects := True; 这种,该怎么判断其中的Obj是不是被Free掉了?可以为TNewObject类型写一个helper,替换free方法,在里面检查List。不过从设计角度来说。这是一种非常糟糕的设计,强行关联外部对象,增加了耦合度。

    你说的这种办法,我也试过,不过这样就有一个没用的helper存在,它的作用仅仅是用来判断obj是否存在。另外,你说的从设计的角度上来说,这种设计其实很常见,比方说用3个ObjectList存Obj,一个list存在职人员,一个存离职人员,最后一个存所有人员,这里面就一定存在一个obj被多个List引用,当其中一个List删除某一个Obj后,其它List.free的时候,一定会出问题。
      

  5.   

    TObjectList对象有OwnsObjects属性。当设定为True,TObjectList对象将销毁任何从列表中删除的对象。
      

  6.   


    假如一定要用List.OwnsObjects := True; 这种,该怎么判断其中的Obj是不是被Free掉了?可以为TNewObject类型写一个helper,替换free方法,在里面检查List。不过从设计角度来说。这是一种非常糟糕的设计,强行关联外部对象,增加了耦合度。

    你说的这种办法,我也试过,不过这样就有一个没用的helper存在,它的作用仅仅是用来判断obj是否存在。另外,你说的从设计的角度上来说,这种设计其实很常见,比方说用3个ObjectList存Obj,一个list存在职人员,一个存离职人员,最后一个存所有人员,这里面就一定存在一个obj被多个List引用,当其中一个List删除某一个Obj后,其它List.free的时候,一定会出问题。既然你的需求是既可以自行释放对象,也可以让它的所有者(比如list)释放,也只能用helper替换Free方法来处理,我的意思是用helper来处理释放对象的同步不是好的设计,当然你这种需求本身就不是好的设计,如果是不支持class helpers功能的语言,象C++,这种需求就无法实现,只能通过合理的设计来解决,比如规定要么手动释放对象,要么由所有者负责释放,不能混合。