Chức năng
function ReturnRec: TRec<Integer>;
là ngữ nghĩa tương đương với thủ tục
procedure ReturnRec(var Result: TRec<Integer>);
[Tôi khá chắc chắn rằng ai đó từ Embarcadero, có lẽ Barry Kelly hay Alan Bauer nói này ở đâu đó nhưng tôi không thể tìm thấy tham chiếu tại thời điểm này.]
Trong trường hợp thứ hai, trình biên dịch giả định rằng bản ghi sẽ được khởi tạo (nếu cần) trước khi nó được chuyển đến ReturnRec và không tạo bất kỳ mã khởi tạo nào cho rec bên trong ReturnRec. Tôi giả sử rằng cùng một đường dẫn mã bên trong trình biên dịch được lấy cho ví dụ đầu tiên và đó là lý do tại sao kết quả không được khởi tạo.
Dù sao, giải pháp rất đơn giản:
function TTestClass.ReturnRec : TRec <Integer>;
begin
Result.Intf := TInterfacedObject.Create;
end;
Chỉ cần giả định trình biên dịch mà biết những gì nó làm và phân công giao diện và tất cả mọi thứ sẽ chỉ làm việc tốt.
EDIT
Sự cố bạn đã xảy ra từ vòng lặp 'for'. Mã của bạn
for I := 1 to 1000 do
Rec := Test.ReturnRec;
được biên dịch vào một cái gì đó như thế này:
var
result: TRec<Integer>;
Initialize(result);
for I := 1 to 1000 do begin
Test.ReturnRec(result);
rec := result;
end;
Đó là lý do tại sao bạn đang sử dụng lại cùng một kỷ lục khắp nơi và đó là lý do tại sao Result.Intf chưa được định hình chỉ lần đầu tiên.
EDIT2
Bạn có thể đánh lừa trình biên dịch bằng cách di chuyển t.ReturnRec gọi ra khỏi vòng lặp thành một phương pháp riêng biệt.
procedure GetRec(t: TTest; var rec: TRec);
begin
rec := t.ReturnRec;
end;
for i := 1 to 1000 do
GetRec(t, rec);
Bây giờ biến kết quả ẩn sống trong thủ tục GetRec và được khởi tạo mỗi khi GetRec được gọi.
Xác nhận không thực hiện được trong lần chạy đầu tiên hoặc thứ hai của vòng lặp? – Johan
@Smasher FWIW, đây là những gì tôi đã nghĩ đến khi tôi viết câu trả lời sai: http://stackoverflow.com/questions/5102843/delphi-function-result-not-emptied-during-for-loop –