Function
function ReturnRec: TRec<Integer>;
Semantically equal to procedure
procedure ReturnRec(var Result: TRec<Integer>);
[Iβm pretty sure that someone from Embarcadero, probably Barry Kelly or Alan Bauer, stated this somewhere, but I canβt find the link for now.]
In the second case, the compiler assumes that the record will be initialized (if necessary) before it is passed to ReturnRec, and will not generate any initialization code for rec inside ReturnRec. I assume that the same code path inside the compiler is taken for the first example and why the result is not initialized.
In any case, the solution is simple:
function TTestClass.ReturnRec : TRec <Integer>; begin Result.Intf := TInterfacedObject.Create; end;
Suppose the compiler knows what it does and assigns an interface, and everything will work fine.
EDIT
The problem that arises comes from the 'for' loop. Your code
for I := 1 to 1000 do Rec := Test.ReturnRec;
consists of the following:
var result: TRec<Integer>; Initialize(result); for I := 1 to 1000 do begin Test.ReturnRec(result); rec := result; end;
This is why you reuse the same entry, and therefore Result.Intf is not initialized only the first time.
EDIT2
You can trick the compiler by moving t.ReturnRec to call from the loop into a separate method.
procedure GetRec(t: TTest; var rec: TRec); begin rec := t.ReturnRec; end; for i := 1 to 1000 do GetRec(t, rec);
Now the hidden result variable lives in the GetRec procedure and is initialized every time GetRec is called.