列出实施情况并记录

发布于 2024-12-21 16:07:24 字数 1307 浏览 4 评论 0原文

此问题的后续问题:(请注意,这不是重复的,我在这里寻求替代方案)。

有什么办法可以完成以下工作:

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 技术交流群。

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

发布评论

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

评论(1

心不设防 2024-12-28 16:07:24

如果我理解正确的话,这应该可以正常工作:

function ReturnHandles : List <THandle>;
begin
  Finalize(Result);
  Result.Add (2);
  Result.Add (3);
end;

Finalize 调用将确保所有托管类型都设置为nil,我相信这是您的意图。

这个问题与您之前的问题非常密切相关,我认为您可以利用 out 参数来简化代码。函数结果隐式是一个 var 参数,但如果您使用显式 out 参数,它将根据您的需要初始化托管类型。

procedure InitializeHandles(out Handles : List <THandle>);
begin
  Handles.Add (2);
  Handles.Add (3);
end;

就我个人而言,由于您要在组合中引入接口,所以我想我会倾向于一路走下去并专门使用接口。或者使用标准类并接受 try/finally 生命周期管理的需要。

This should work fine if I understand you correctly:

function ReturnHandles : List <THandle>;
begin
  Finalize(Result);
  Result.Add (2);
  Result.Add (3);
end;

The Finalize call will ensure that all managed types are set to nil 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 a var parameter, but if you used an explicit out parameter it will initialise the managed types as you desire.

procedure InitializeHandles(out Handles : List <THandle>);
begin
  Handles.Add (2);
  Handles.Add (3);
end;

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.

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