Función
function ReturnRec: TRec<Integer>;
es semánticamente igual al procedimiento
procedure ReturnRec(var Result: TRec<Integer>);
[Estoy bastante seguro de que alguien de Embarcadero, probablemente Barry Kelly o Alan Bauer declaró esto en alguna parte, pero no puedo encontrar la referencia en este momento.]
En el segundo caso, el compilador supone que la grabación se inicializará (si es necesario) antes de pasarla a ReturnRec y no crea ningún código de inicialización para rec dentro de ReturnRec. Supongo que se toma la misma ruta de código dentro del compilador para el primer ejemplo y es por eso que el resultado no se inicializa.
De todos modos, la solución es simple:
function TTestClass.ReturnRec : TRec <Integer>;
begin
Result.Intf := TInterfacedObject.Create;
end;
a suponer que el compilador sabe lo que está haciendo y asignar la interfaz y todo funcionará bien.
EDITAR
El problema que tiene se produce a partir del bucle 'para'. Su código
for I := 1 to 1000 do
Rec := Test.ReturnRec;
se compila en algo como esto:
var
result: TRec<Integer>;
Initialize(result);
for I := 1 to 1000 do begin
Test.ReturnRec(result);
rec := result;
end;
Por eso va a reutilizar mismo registro por todas partes y es por eso que no está inicializado Result.Intf sólo la primera vez.
Edit2
Puede engañar al compilador moviendo t.ReturnRec llamar a cabo a partir del bucle en un método separado.
procedure GetRec(t: TTest; var rec: TRec);
begin
rec := t.ReturnRec;
end;
for i := 1 to 1000 do
GetRec(t, rec);
Ahora la variable de resultado oculta vive en el procedimiento GetRec y se inicializa cada vez que se llama a GetRec.
¿La aserción falla en la primera o segunda ejecución del ciclo? – Johan
@Smasher FWIW, esto es en lo que estaba pensando cuando escribí mi respuesta incorrecta: http://stackoverflow.com/questions/5102843/delphi-function-result-not-emptied-during-for-loop –