列出实施情况并记录
此问题的后续问题:(请注意,这不是重复的,我在这里寻求替代方案)。
有什么办法可以完成以下工作:
type
List <T> = record
private
FList : TList <T>;
FGuard : IInterface,
procedure CheckCreated;
public
procedure Add(const Value : T);
end;
procedure List <T>.CheckCreated;
begin
if (FGuard = nil) then
begin
FList := TList <T>.Create;
FGuard := TGuard.Create (FList); // guard calls free on list in destructor
end;
end;
procedure List <T>.Add (const Value : T);
begin
CheckCreated;
FList.Add (Value);
end;
理想情况下,我想像这样使用它:
function ReturnHandles : List <THandle>;
begin
Result.Add (2);
Result.Add (3);
end;
正如链接问题的答案中所解释的,这不起作用(这确实很遗憾)。它不会在每次调用时创建新列表。
不幸的是,这也不起作用:
function ReturnHandles : List <THandle>;
begin
Initialize (Result);
Result.Add (2);
Result.Add (3);
end;
它泄漏了保护接口和所有列表,因为 Initialize
只是覆盖了接口引用,而没有减少引用计数。
有什么办法可以让这个工作吗?或者您是否建议将其作为界面而不是记录,并且只使用构造线?
function ReturnHandles : List <THandle>;
begin
Result := List <T>.Create;
Result.Add (2);
Result.Add (3);
end;
感谢您的帮助!
Follow-up question to this question: (note that this is not a duplicate, I'm asking for alternatives here).
Is there any way to make the following work:
type
List <T> = record
private
FList : TList <T>;
FGuard : IInterface,
procedure CheckCreated;
public
procedure Add(const Value : T);
end;
procedure List <T>.CheckCreated;
begin
if (FGuard = nil) then
begin
FList := TList <T>.Create;
FGuard := TGuard.Create (FList); // guard calls free on list in destructor
end;
end;
procedure List <T>.Add (const Value : T);
begin
CheckCreated;
FList.Add (Value);
end;
Ideally I want to use it like this:
function ReturnHandles : List <THandle>;
begin
Result.Add (2);
Result.Add (3);
end;
As explained in the answers to the linked question, this does not work (which is really a pitty). It will not create a new list on each call.
Unfortunately this does not work either:
function ReturnHandles : List <THandle>;
begin
Initialize (Result);
Result.Add (2);
Result.Add (3);
end;
It leaks the guard interfaces and all the lists, because Initialize
just overwrites the interface reference without decrementing the reference count.
Is there any way to make this work? Or would you suggest making this an interface instead of a record and just live with the construction line?
function ReturnHandles : List <THandle>;
begin
Result := List <T>.Create;
Result.Add (2);
Result.Add (3);
end;
Thanks for your help!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果我理解正确的话,这应该可以正常工作:
Finalize
调用将确保所有托管类型都设置为nil
,我相信这是您的意图。这个问题与您之前的问题非常密切相关,我认为您可以利用
out
参数来简化代码。函数结果隐式是一个var
参数,但如果您使用显式out
参数,它将根据您的需要初始化托管类型。就我个人而言,由于您要在组合中引入接口,所以我想我会倾向于一路走下去并专门使用接口。或者使用标准类并接受 try/finally 生命周期管理的需要。
This should work fine if I understand you correctly:
The
Finalize
call will ensure that all managed types are set tonil
which I believe is your intent.This question is very closely related to your previous question and I think that you could make use of
out
parameters to simplify the code. A function result is implicitly avar
parameter, but if you used an explicitout
parameter it will initialise the managed types as you desire.Personally, since you are introducing an interface into the mix, I think I would be inclined to go all the way and use interfaces exclusively. Or use standard classes and accept the need for try/finally lifetime management.