Suppose I have a function:
function someFunction: TStringList;
begin
result:=TStringList.Create;
if someConditionIsTrue then
result:=doSomething;
//other code
end;
And the function doSomething:
function doSomething: TStringList;
begin
result:=TStringList.Create;
result.Add(something);
end;
If I run this code everything works as hoped, but I'm still wondering if this is the "proper" way to pass around an object like a stringlist?
The stringlists are never freed, and I wonder if passing around objects this way could get complicated or confusing when it came to debugging or someone else trying to understand the code.
The "proper" approach is for you to establish your own rules for how things get destroyed. It's fine to create objects in a function result, but only if you are following your own strict rules.
In your case, SomeFunction
has a memory leak. First, you create a TStringList
, and then if some condition is met, you create another TStringList
in its place, completely disregarding the first one. Thus, leaking memory.
DoSomething
shouldn't be a function returning a string list, if there's a possibility that you might already have one created. Instead, just make it a procedure...
procedure DoSomething(AList: TStringList);
begin
AList.Add(Something);
end;
Once you do that, then SomeFunction
should look like this:
function someFunction: TStringList;
begin
Result:= TStringList.Create;
if someConditionIsTrue then
DoSomething(Result);
//other code
end;
"The stringlists are never freed"
I hope this isn't by design. Everything you create must be free'd at some point, especially if you have functions that create their result. The only exception is if you create something that lives for the entire duration of the application, and even then it's extreme common-ground to free them anyway.
On that note, the only time I ever create an object in a function result is when I'm encapsulating multiple lines of code which would otherwise be duplicated many times. For example, creating a query.
Instead of repeating this code...
Q:= TADOQuery.Create(nil);
Q.Connection:= MyDatabaseConnection;
Q.SetSomeOtherProperties;
...I put it in a function...
function CreateQuery: TADOQuery;
begin
Result:= TADOQuery.Create(nil);
Result.Connection:= MyDatabaseConnection;
Result.SetSomeOtherProperties;
end;
Then, I can simply call this function whenever I need to repeat that code...
Q:= CreateQuery;