2011-12-16 9 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

ロブは最後の質問で、「Initialize」はgabrの答えに誤りがあると説明しました。だからあなたはそれを使ってはいけません。 –

+0

これは私が書いたものです。この作業を行うための他の方法がある場合、またはオブジェクトを含む値の型を作成できない場合は、ご質問 – jpfollenius

+0

ここでは、Delphiのルールに反対しています。あなたはこのようにして「道路」を一定の距離だけ下っているかもしれませんが、RECORDタイプのアプローチには大きなコストがかかります。 –

答えて

2

私が正しくあなたを理解していればこれが正常に動作する必要があります:

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

Finalize呼び出しは、すべての管理対象の種類が、私はあなたの意思であると考えていnilに設定されていることを確認します。

この質問は以前の質問と非常に密接に関連しており、コードを簡略化するためにoutパラメータを使用できると思います。関数の結果は暗黙的にvarパラメータですが、明示的なoutパラメータを使用した場合は、必要に応じてマネージ型を初期化します。個人的に

procedure InitializeHandles(out Handles : List <THandle>); 
begin 
    Handles.Add (2); 
    Handles.Add (3); 
end; 

は、あなたがミックスにインターフェイスを導入しているので、私はすべての道を行くと、もっぱらのインターフェイスを使用するように傾斜させることだと思います。または、標準クラスを使用して、try/finally生涯管理の必要性を受け入れます。

+0

ありがとう、私はその情報を逃した!しかし、それほど直感的ではありません。私はインターフェイスのソリューションに行くかもしれません。残念ながら、私はオペレータオーバーロードを使用する可能性を失うでしょう:( – jpfollenius

+0

昨日あなたの質問までこの 'Initialize'関数について聞いたことがありませんでした! –

+0

入力をいただきありがとうございます。言語は本当に制限しています。このように使用する場合、すべての呼び出し側が 'Finalize'を呼び出すように強制する必要があります。そうしないと、リスト内の演算子オーバーロードと汎用メソッドをあきらめなければなりません。言語をより汎用性のあるものにするために可能な改善がまだあります。 – jpfollenius

関連する問題