0

私はDelphi 2007で作業しています。コードを整理しています。私は非常に多くの手続きの中で同じタイプのいくつかの異なる変数を宣言していることに気付くようになりました。作成する関数にオブジェクトのグループを渡すにはどうしたらいいですか?

たとえば、私が今見ている手続きは、4つの異なる文字列リストを宣言し、それぞれにvar1 := TStringList.Createと入力する必要があります。

私は、変数のオープンな配列、4つの変数のリスト、そしてすべてを作成する手順を立てる考えがありました。呼び出しはこのようなものになります

CreateStringLists([var1,var2,var3,var4]); 

私の知る限り、あなたはオープンアレイを参照して渡すことはできませんので、私が望んでいたことはしません。誰もこれについて興味深いアイデアを持っていますか?

答えて

4

Delphiでは何か(またはほとんどすべて)を行うことができます。私はトリックが可能であることを知るために、使用するには、以下のコードをお勧めしません:

type 
    PStringList = ^TStringList; 

procedure CreateStringLists(const SL: array of PStringList); 
var 
    I: Integer; 

begin 
    for I:= 0 to High(SL) do begin 
    SL[I]^:= TStringList.Create; 
    end; 
end; 

procedure TForm1.Button2Click(Sender: TObject); 
var 
    SL1, SL2, SL3: TStringList; 

begin 
    CreateStringLists([@SL1, @SL2, @SL3]); 
    SL3.Add('123'); 
    Caption:= SL3[0]; 
    SL1.Free; 
    SL2.Free; 
    SL3.Free; 
end; 
+0

+1私はこれをやるために自分自身を持ち込むことはできないだろうと思っていますが、タイプセーフでかなり卑劣です。 –

+0

+1あなたは私を打つ!私は今、単純なポインタに基づいて独自の実装を持って、私はあなたの答えに気づいたときにTStringListへのポインタを使用するようにアップグレードしていた。 :) – jachguate

+0

もちろん、例外をCreateStringListsプロシージャで認識させる必要があるので、それらのすべてが正常に作成されるか、作成されたすべてが解放されて例外的な方法でルーチンを終了します。 – jachguate

1

2、3、4などのパラメータで一連のオーバーロードされたバージョンを作成できます。例:

procedure CreateStringLists(var L1, L2: TStringList); overload; 
procedure CreateStringLists(var L1, L2, L3: TStringList); overload; 
procedure CreateStringLists(var L1, L2, L3, L4: TStringList); overload; 

procedure CreateStringLists(var L1, L2: TStringList); 
begin 
    L1 := nil; 
    L2 := nil; 
    Try 
    L1 := TStringList.Create; 
    L2 := TStringList.Create; 
    Except 
    FreeAndNil(L2); 
    FreeAndNil(L1); 
    raise; 
    End; 
end; 

// etc. 

私がこれを行っていた場合、コードを生成するスクリプトを作成します。

私自身のコードでは、その機能の開始時にInitialiseNil(L1, L2)、例外ハンドラではFreeAndNil(L2, L1)と書いています。 InitialiseNilFreeAndNilは非常に単純なPythonスクリプトによって生成された関数であり、再実行できるようにコメントとしてコードベースに含まれています。上で定義したCreareStringListsのようなルーチンは、一度にすべてのルーチンを解放するルーチンがあれば役に立ちます。これは次のように記述することができます:

CreateStringLists(L1, L2); 
Try 
    // do stuff with L1, L2 
Finally 
    FreeAndNil(L2, L1); 
End; 

は最後に、私は必ずしもこれを行うだろうと言っていないんだけど、これは質問へのナイーブとの直接の答えとして意味しています。 @ T.E.D.これを行う必要性は、コードベースの深刻な問題を示唆しています。

+0

+1私はこれをSergのソリューションと組み合わせます:自分のプライベートを持って、あなたのコードをよりきれいに公開します。 –

1

実際、4つのコンストラクタで何が問題になっていますか?

+2

実際、これはコメントのように見えますが、実際の答えとは異なります。 – jachguate

+0

機能的には何もありません。視覚的に見ると、私が見ているコードは短くて見やすくなります。 – Tim

5

多くの場合、リファクタリングでは、非常にのコードを見る必要があります。このような操作を「クリーンアップ」する理由は何でしょうか。ほとんどの場合、これらの操作を何もしないでください。

この場合、4つの別々の文字列リストを処理する必要があるルーチンが1つあります。それは良い結束を持つ可能性は非常に高いように思われません。代わりに、4回呼び出される1つの文字列リスト処理ルーチンでなければなりません。ですから、私は本当にこのルーチンをもっときれいにする方法についてコメントするよりも、ルーチン全体を見たいと思っています。

+0

+1大きな画像を見て! –

+0

私はいくつかのシンプルなプレゼンテーションソフトウェアを開発しており、これは特にスライド(パワーポイントesq)プレゼンテーションに関連しています。それぞれのスライドには、本文、タイトル、著作権の3つの異なる領域があります。そして、スライドがディスクに保存される方法であるテキストファイルからテキストを解析する別の文字列リスト。彼らはすべてユニークな目的のために作られています。私はあなたの答えが好きです...私はこれについて考えるつもりです。 – Tim

1

それはあなたのコンテキストで理にかなっている場合は、専門のTObjectListを内部宣言を集約することができます。

type 
    TMyList<T:class,constructor> = class(TObjectList<T>) 
    public 
    procedure CreateItems(const ACount : integer); 
    end; 

procedure TMyList<T>.CreateItems(const ACount: integer); 
var 
    Index: Integer; 
begin 
    for Index := 0 to (ACount - 1) do Add(T.Create); 
end; 

// Test procedure 
procedure TestMe; 
var 
    MyStringsList : TMyList<TStringList>; 
begin 
    MyStringsList := TMyList<TStringList>.Create(True); 
    MyStringsList.CreateItems(10); 
    // ... 
    FreeAndNil(MyStringsList); 
end; 

あなたのリストを専門にすることができます。

関連する問題