Dorzucę swoje 3 grosze...
Nigdy, ale to nigdy nie powinno się pisać funkcji, które zwracają w Result instancję obiektu. To oczywiste proszenie się o kłopoty, bo taka funkcja wprowadza zamieszanie. Co w przypadku, kiedy funkcja nie może zwrócić instancji obiektu (bo cokolwiek)? Powinna zwrócić nil?
Poza tym - kto ma zniszczyć ten obiekt? Bo zapis jak podano wyżej sugeruje, że to funkcja zarządza cyklem życia obiektu - a tak nie jest.
Można napisać np. taki kod:
Test.Transparent := True;
I wszystko jest teoretycznie OK, poza gwarantowanym wyciekiem pamięci.
Dlatego też, zgodnie z zasadami programowania defensywnego, powinno to wyglądać np. tak:
function Test(AStream : TMemoryStream; var AGraphic : TGraphic) : Boolean;
begin
try
if Assigned(AStream) then
begin
AGraphic := TRafPic.Create(AStream); //AStream zostanie rozpoznane jako jpg/bmp/tiff/gif/png itp
Result := True;
end
else
Result := False;
except
on E: Exception do
begin
Result := False;
raise;
end;
end;
end;
I samo użycie:
var
lGraphic : TGraphic;
begin
if Test(lStream, lGraphic) then
lGraphic // coś tam
end;
Dlaczego tak jest lepiej? Ponieważ:
- Programista musi zadeklarować zmienną do której dostanie efekt działa funkcji. Co przy funkcji, która zwraca instancję obiektu, nie jest wymogiem.
- Jak programista sam zadeklaruje zmienną, to od razu widzi, że musi ją sam zwolnić.
- Ma pewność, czy wywołanie funkcji się powiodło - wystarczy sprawdzić czy
Result = True