Wenn es um das zurückgeben von manuell gemanageten Ressourcen geht (worunter Klassen fallen, aber auch z.B. FileHandles) gibt es zwei Probleme, das erste ist das in diesem Fall der Rückgabewert immer beachtet werden muss. In (Object)Pascal ist es komplett legal den Funktionswert zu ignorieren, das würde dann natürlich zu datenverlust und damit in diesem Fall zu Speicherlecks führen:
Code: Alles auswählen
function Foo: TStringList;
...
begin
Foo; // Erzeugt ein Speicherleck
end;
D.h. allein von dieser seite aus macht es mehr sinn das Ergebnis als zusätzlichen Parameter zu übergeben, da das den Nutzer zwingt es entgegen zu nehmen. Man sollte seinen Code immer so bauen das es so schwer wie Möglich ist damit was falsch zu machen, und hier ist ist ein extra Parameter ein weg den Syntaxcheck des Compilers zu nutzen um solche Fehler zu vermeiden.
Das zweite sind exceptions. Wenn eine Exception aufkommt sollte man davon ausgehen das das Ergebnis der Funktion nicht aussagekräftig ist, da du von außen, im allgemeinen ja nicht weißt wo die exception aufgetreten ist und in welchem State das Result zu diesem Zeitpunkt war. D.h. du kannst nicht sowas machen:
da X bei einer Exception undefiniert sein kann kann X.Free selbst einen Fehler auslösen. Sondern es muss so gemacht werden:
So wie man das auch mit dem Konstruktor Create macht. Das Problem hierbei ist das wenn Foo eine Exception wirft nachdem das Result erzeugt wurde, muss es gefreed werden, und das muss innerhalb von Foo geschehen:
Code: Alles auswählen
function Foo: TStringList;
begin
...
Result := TStringList.Create;
try
except
Result.Free;
raise;
end;
end;
Das ist übrigens auch was der Compiler automatisch beim Konstructor Create einfügt, damit Exceptions darin kein Speicherleck verursachen. Bei normalen Funktionen muss man das halt selbst machen.
Gleichzeitig muss man aufpassen das kein Parametrisiertes Exit vorkommt, bzw wenn, das dann Result gefreed wird:
Code: Alles auswählen
Result := TStringList.Create;
...
Result.Free; // muss vor parametrisiertem exit immer aufgerufen werden
Exit(nil);
Das führt einfach nur mehr Komplexität ein, und ist was was man sehr einfach vergessen oder Falsch machen kann.
Klar ist das Funktionsergebnis eigentlich immer schöner als einen Parameter zu übergeben, aber unter diesen Gesichtspunkten sollte man es, um die Komplexität gering zu halten und möglichst Robusten Codes zu schreiben, doch besser als Parameter zurückgeben