Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delphi function return class object

Tags:

delphi

In addition to this question I have made some tests and researches on the docwiki. My conclusion is that this kind of code should work without memory leaks:

function testResultObject: TClassA;
begin
 Result := TClassA.Create;
 Result.DoSomething;
end;

And then somewhere I can call the above code in this manner:

var k: TClassA;
begin

 k := testResultObject;
 try
  //code code code
 finally
  k.Free;
 end;

end;

As Remy suggested in the answer it's better to avoid this way of doing things and instead use something like testResultObject(x: TClassA): boolean. In this case the return true/false can tell me if everything went fine and I am passing an object already created.

Look at this code:

function testResultObject: TClassA;
begin

 Result := TClassA.Create;

 try
  Result.DoSomething;
 except
  Result.Free;
 end;

end;

The problem with the first version above of the function is that DoSomething could raise an exception and if so I'll leak memory. Can the second implementation with try-except be a solution? For sure later I'll have to check if the result is assigned or nil.

I agree that (as already said above) the testResultObject(x: TClassA): boolean would be better. I was just wondering if the return-a-class function way could be fixed as I've written.

like image 416
Raffaele Rossi Avatar asked Dec 02 '22 11:12

Raffaele Rossi


1 Answers

Your code has serious problems. In case of an error, it swallows the exception, and returns an invalid object reference.

This is easy to fix. The canonical way is as follows:

function testResultObject: TClassA;
begin
  Result := TClassA.Create;    
  try
    Result.DoSomething;
  except
    Result.Free;
    raise;
  end;
end;

Either the function succeeds and returns a new object. Or it fails, cleans up after itself, and raises an exception.

In other words, this function looks and behaves just like a constructor. You consume it in the same way:

obj := testResultObject;
try
  // do things with obj
finally
  obj.Free;
end;
like image 199
David Heffernan Avatar answered Dec 04 '22 23:12

David Heffernan