We help IT Professionals succeed at work.

function returning TStringList

lizzzard
lizzzard asked
on
Hi,

can I let a function return a Tstringlist? If yes how? If I do it like this example I get an access violation (which doesn't suprise me btw):

function TMainForm.GetFileContent(FileName : String) : TStringList;
begin
 result.LoadFromFile(Filename);
end;

or

function TMainForm.Test(TestComment : String) : TStringList;
var Temp : TStringList;
begin
 Temp := TStringList.Create;
 Temp.Add(TestComment);
 result.assign(Temp);
 Temp.Free;
end;

Thanks,
Lizzzzzz
Comment
Watch Question

Commented:
The standard way to do this is like do

procedure DoSomething(FileName: string; Result: TStrings);
begin
  do something
  Result.Add('sdfsdfsdf');
  etc
  etc
end;

That way the calling routine is responsible for creating / freeing the TStringList object.
partly agree cubud ,

but do u think result is a reserved word?
if you really want to do so try:

function ReturnTStringList:String;
var
 st:TstringList;
begin
 st.loadfromfile('a.txt');
 result := st.gettext;
 st.free;
end;

procedure useit;
var
 st:TstringList;
begin
 st.loadfromfile('a.txt');
 st.settext(ReturnTStringList);
end;

Commented:
You can return a TStringList, however, you have to instantiiate it before using it (as you have to with any other object):

function TMainForm.GetFileContent(FileName : String): TStringList;
begin
    Result:=TStringList.Create;
    Result.LoadFromFile(Filename);
end;

Be aware, however, that a function like this will create a new TStringList instance everytime you call it. So, in your code, this would be used like this:

    Content:=GetFileContent('Test.TXT'); // replaces the TStringList.Create call
    try
        // work with Content here
    finally
        Content.Free;
    end;

If there already was an instance in Content, you should free it before re-assigning it a new value with your function:

    // Assumption: Content oints to a TStringList already
    Content.Free;
    Content:=GetFileContent('Test.TXT');
Commented:
Okay

Point 1) Result is only a reseved word in a Function, I wrote a Procedure, so my code is 100% valid.  Please check you comments are valid before you post them.

Point 2)  This code ....
Content:=GetFileContent('Test.TXT'); // replaces the TStringList.Create call
try
  // work with Content here
finally
  Content.Free;
end;

Is not a good solution at all, if GetFileContent fails at the LoadFromFile line you have unfreed memory.  You would have to put a try ... except in your function.  It is all quite messy when you could just do

procedure GetFileContent(Filename: string; Result: TStrings);
begin
  Assert(Result <> nil, 'Result is nil');
  Result.LoadFromFile(Filename);
  //more here
end;

MyFileInfo := TStringList.Create;
try
  GetFileContent('c:\autoexec.bat', MyFileInfo);
finally
  MyFileInfo.Free;
end;

AND another added benefit is you can use the same procedure to act on VCL controls such as TComboBox and TListBox (which is why the type is TStrings in the procedure and not TStringList).

GetFileContent('c:\autoexec.bat', Listbox1.Items);
GetFileContent('c:\autoexec.bat', Combobox1.Items);

Pete
====
http://www.HowToDoThings.com (Delphi articles)
http://www.Stuckindoors.com/delphi (Open source)
CERTIFIED EXPERT
Top Expert 2004

Commented:
function whatever : tstringlist;
begin
  result := tstringlist.create;
  //anyone doing with the tstringlist
end;

don't forget to free the tstringlist,
somerwhere in your caller

meikl ;-)

Author

Commented:
Ok,

Thank you all guys for your comments. Somehow the function actually returning the TStringList as result I feel to be more elegant. However for reasons you mentioned, I prefer to use the cubud solution, as I already do. The reason I posted ths question was I wanted to know if there was a nice and safe way to let the function return the TSTringList as result. You all answered that now,

Thanks again,
Lizzzzz