如何将一组对象传递给函数进行创建?

时间:2011-01-05 19:58:29

标签: delphi delphi-2007 variable-initialization open-array-parameters

所以我在Delphi 2007工作,我正在清理我的代码。我注意到在很多程序中我声明了许多相同类型的不同变量。

例如我现在正在查看的一个程序我声明了4个不同的字符串列表,我必须为每个字符串键入var1 := TStringList.Create

我有一个想法是创建一个过程,该过程接受一个开放的变量数组,我的4个变量列表,然后创建所有变量。电话会是这样的

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

但据我所知,你不能通过引用传递开放数组,因此不能做我希望的事情。有没有人对此有任何有趣的想法?

5 个答案:

答案 0 :(得分:5)

通常在重构时,您需要使用非常的代码视图。为什么“清理”这样的几个操作,很可能你根本不应该做任何这些操作?

在这种情况下,我似乎怀疑你有一个例程需要处理4个单独的字符串列表。这似乎不太可能具有良好的凝聚力。也许它应该是一个称为四次的字符串列表处理例程。所以我真的很想看看整个例行程序,而不是评论如何使这个例子变得更漂亮。

答案 1 :(得分: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;

答案 2 :(得分: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。状态,需要这样做表明代码库中存在更深层次的问题。

答案 3 :(得分:1)

实际上,4个构造函数有什么问题?

答案 4 :(得分: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;

所以你可以专门列出你的名单。