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

piwo6bdm  于 2023-05-22  发布在  其他
关注(0)|答案(3)|浏览(190)

如何从函数返回字符串列表已经讨论过很多次了。我的代码序列版本1只是一个概述如何做到这一点。

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;

是否有任何选项来修复版本2中的内存泄漏“没有额外的代码”,这种方法有多危险,这会导致任何失败,如果我的字符串列表只是几个字符串项,内存不足的问题不会发生?

rpppsulh

rpppsulh1#

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

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

sbdsn5lh2#

如果你要从函数返回一个新示例化的对象,有一个模式。是这样的:

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中的内存泄漏“没有额外的代码”,这种方法有多危险,这会导致任何失败,如果我的字符串列表只是几个字符串项,内存不足的问题不会发生?
如果你返回了一个新示例化的对象,那么调用者就不能避免该对象的所有权责任。

laximzn5

laximzn53#

如前所述,您需要向函数和调用者添加额外的代码,以便 * 正确地 * 管理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;

相关问题