2011-12-16 110 views
4

後續問題this question :(注意,這不是重複的,我在這裏要求替代品)。列表實現與記錄

有沒有什麼辦法讓下面的工作:

type 
    List <T> = record 
    private 
    FList : TList <T>; 
    FGuard : IInterface, 
    procedure CheckCreated; 
    public 
    procedure Add(const Value : T); 
    end; 

procedure List <T>.CheckCreated; 
begin 
if (FGuard = nil) then 
    begin 
    FList := TList <T>.Create; 
    FGuard := TGuard.Create (FList); // guard calls free on list in destructor 
    end; 
end; 

procedure List <T>.Add (const Value : T); 
begin 
CheckCreated; 
FList.Add (Value); 
end; 

理想我想用這樣的:

function ReturnHandles : List <THandle>; 
begin 
Result.Add (2); 
Result.Add (3); 
end; 

正如答案的鏈接的問題解釋說,這不工作(這真的是一個可憐的人)。它不會在每次通話中創建一個新列表。

不幸的是這不工作之一:

function ReturnHandles : List <THandle>; 
begin 
Initialize (Result); 
Result.Add (2); 
Result.Add (3); 
end; 

它泄漏防護界面和所有的名單,因爲Initialize只覆蓋不遞減引用計數的接口引用。

有什麼辦法可以使這項工作?或者你會建議把這個界面變成一個界面,而不是一個記錄,只是和建築線一起住?

function ReturnHandles : List <THandle>; 
begin 
Result := List <T>.Create; 
Result.Add (2); 
Result.Add (3); 
end; 

感謝您的幫助!

+0

Rob在你上一個問題中解釋說`Initialize`是gabr答案中的一個錯誤。所以不,你不應該使用它。 – 2011-12-16 10:53:27

+0

這就是我寫的......問題是如果有其他方法可以使這項工作,或者如果只是不可能創建包含對象的值類型 – jpfollenius 2011-12-16 10:55:04

回答

2

這應該正常工作,如果我理解正確:

function ReturnHandles : List <THandle>; 
begin 
    Finalize(Result); 
    Result.Add (2); 
    Result.Add (3); 
end; 

Finalize通話將確保所有託管類型設置爲nil我相信這是你的意圖。

這個問題與你以前的問題非常接近,我認爲你可以使用out參數來簡化代碼。函數結果隱含地爲var參數,但如果使用明確的out參數,則會根據需要初始化託管類型。個人而言,由於您正在向組合中引入一個界面,因此我認爲我會傾向於全部使用界面,並且僅使用界面。或者使用標準類,並接受嘗試/最終生命週期管理的需要。