0

私は Delphi 2007 で作業しており、コードをクリーンアップしています。非常に多くの手続きで、同じ型のさまざまな変数を宣言していることに気づきました。

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

私は、変数のオープン配列、4 つの変数のリストを取り、それらすべてを作成する手順を作成するという考えを持っていました。呼び出しは次のようになります

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

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

4

5 に答える 5

5

多くの場合、リファクタリングでは、コードを非常に広い視野で見る必要があります。ほとんどの場合、これらの操作をまったく行うべきではないのに、なぜこのようないくつかの操作を「クリーンアップ」するのでしょうか?

この場合、4 つの別個の文字列リストを処理する必要があるルーチンが 1 つあるとは思えません。まとまりが良いとは思えません。おそらく代わりに、1 つの文字列リスト処理ルーチンを 4 回呼び出す必要があります。ですから、これをより美しくする方法についてコメントするのではなく、ルーチン全体を見たいと思います.

于 2011-01-05T20:06:44.113 に答える
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;
于 2011-01-05T20:20:04.390 に答える
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;

したがって、リストを専門化できます。

于 2011-01-06T10:02:35.547 に答える
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;

最後に、私は必ずしもこれを行うと言っているわけではありませんが、これは質問に対する素朴で直接的な答えとして意図されています. @TED が述べているように、これを行う必要があることは、コードベースのより深い問題を示唆しています。

于 2011-01-05T20:02:56.137 に答える
1

実際、4 つのコンストラクターの問題点は何ですか?

于 2011-01-05T20:05:03.490 に答える