TStringlist作为函数结果,最小代码序列

huangapple go评论59阅读模式
英文:

TStringlist as function result, minimal code sequence

问题

以下是您要翻译的内容:

"如何从函数返回Stringlist已经讨论了很多次。
我的代码序列版本1只是如何做的简要回顾。

function GetStrings: TStringList;
begin
Result := TStringList.Create;
Result.Add('字符串A');
Result.Add('字符串B');
end;

procedure TForm1.Button1Click(Sender: TObject);
var
stemp: TStringList;
begin
stemp := GetStrings;
MyListBox.Items.AddStrings(stemp);
stemp.Free;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
MyListBox.Items.AddStrings(GetStrings);
end;

是否有选项在版本2中修复内存泄漏而"不需要额外的代码",这种方法到底有多危险,如果我的字符串列表只包含几个字符串项,是否会导致任何故障,不会发生内存问题?"

英文:

How to return a Stringlist from a function has been discussed many time before.
My code sequence version 1 is just a recap how to do it.

function GetStrings : TStringList;
begin
  Result := TStringList.Create;
  Result.Add('string A');
  Result.Add('string B');
end;

procedure TForm1.Button1Click(Sender: TObject);
var stemp : tStringList;
begin
  stemp := GetStrings;
  MyListBox.items.addstrings(stemp);
  stemp.Free;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  MyListBox.items.addstrings(GetStrings);
end;

is there any option to fix the memory leak in version2 with "no extra code", how dangerous is this approach at all, will this cause any failures if my stringlist is just a few string items, out of memory issues will not happen?

答案1

得分: 14

不要使用TStringList作为结果类型,而是使用TArray<string>。当然,这会使version1变得过时。

function GetStrings: TArray<string>;
begin
  var lst := TStringList.Create;
  try
    lst.Add('字符串 A');
    lst.Add('字符串 B');
    Result := lst.ToStringArray;
  finally
    lst.Free;
  end;
end;
英文:

Don't use a TStringList as result type, but a TArray&lt;string&gt;. Of course this makes version1 obsolete.

function GetStrings : TArray&lt;string&gt;;
begin
  var lst := TStringList.Create;
  try
    lst.Add(&#39;string A&#39;);
    lst.Add(&#39;string B&#39;);
    Result := lst.ToStringArray;
  finally
    lst.Free;
  end;
end;

答案2

得分: 4

以下是翻译好的内容:

如果你打算从函数中返回一个新创建的对象,有一个模式可供使用。它如下所示:

function GetStrings: TStringList;
begin
  Result := TStringList.Create;
  try
    Result.Add('string A');
    Result.Add('string B');
  except
    Result.Free;
    raise;
  end;
end;

这个函数的行为类似构造函数。它要么返回一个新创建的对象并将所有权传递给调用者,要么引发异常并在引发之前进行清理。

如果你使用这种模式,那么你需要像使用构造函数创建的对象一样使用它,采用众所周知的模式:

procedure TForm1.Button1Click(Sender: TObject);
var 
  temp: TStringList;
begin
  temp := GetStrings;
  try
    MyListBox.Items.AddStrings(temp);
  finally
    temp.Free;
  end;
end;

现在,关于你的直接问题:

> 是否有选项在“没有额外代码”的情况下修复版本2中的内存泄漏,这种方法究竟有多危险,如果我的字符串列表只包含少量字符串项,会导致任何故障吗,不会发生内存问题吗?

如果你返回一个新创建的对象,那么调用者不能避免对该对象的所有权责任。

英文:

If you are going to return a newly instantiated object from a function, there is a pattern for that. It goes like this:

function GetStrings: TStringList;
begin
  Result := TStringList.Create;
  try
    Result.Add(&#39;string A&#39;);
    Result.Add(&#39;string B&#39;);
  except
    Result.Free;
    raise;
  end;
end;

This function behaves just like a constructor. Either it returns a newly instantiated object, and passes ownership to the caller. Or it raises an exception, and tidies up before raising it.

If you use this pattern, then you need to do so in the same way as you would with an object instantiated by a constructor, using the well known pattern:

procedure TForm1.Button1Click(Sender: TObject);
var 
  temp: TStringList;
begin
  temp := GetStrings;
  try
    MyListBox.Items.AddStrings(temp);
  finally
    temp.Free;
  end;
end;

Now, as for your direct question:

> is there any option to fix the memory leak in version2 with "no extra code", how dangerous is this approach at all, will this cause any failures if my stringlist is just a few string items, out of memory issues will not happen?

If you do return a newly instantiated object, then the caller can't avoid the responsibilities of ownership for that object.

答案3

得分: 4

如其他人所提到的,您需要在函数和调用者两处添加额外的代码,以正确管理TStringList,以确保它始终被释放。

更好的选项是根本不返回TStringList,而是接受调用者想要的任何TStrings对象,然后只需填充它,例如:

procedure GetStrings(Strings: TStrings);
begin
  Strings.BeginUpdate;
  try
    Strings.Add('string A');
    Strings.Add('string B');
  finally
    Strings.EndUpdate;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  GetStrings(MyListBox.Items);
end;
英文:

As others as mentioned, you need to add extra code to both the function and the caller in order to manage the TStringList correctly to ensure it is always freed.

A better option is to not return a TStringList at all, but rather to take in any TStrings object the caller wants and just fill it in, eg:

procedure GetStrings(Strings: TStrings);
begin
  Strings.BeginUpdate;
  try
    Strings.Add(&#39;string A&#39;);
    Strings.Add(&#39;string B&#39;);
  finally
    Strings.EndUpdate;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  GetStrings(MyListBox.Items);
end;

huangapple
  • 本文由 发表于 2023年5月17日 15:00:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/76269322.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定