Como eu posso passar um grupo de objetos para uma função para criação?
-
25-09-2019 - |
Pergunta
Então, eu estou trabalhando em Delphi 2007 e estou arrumando meu código.Eu vim a perceber que em um grande número de procedimentos de eu declarar uma série de diferentes variáveis do mesmo tipo.
por exemplo, a um procedimento que estou olhando agora declaro 4 tipos diferentes de listas de seqüência de caracteres e eu tenho que digitar var1 := TStringList.Create
para cada um deles.
Eu tinha a ideia de fazer um procedimento que teve em aberto matriz de variáveis, minha lista de 4 variáveis e, em seguida, criá-los todos.A chamada seria algo como isto
CreateStringLists([var1,var2,var3,var4]);
Mas, como é do meu conhecimento que você não pode passar a abrir matriz por referência e, portanto, não faça o que eu estava esperando.Alguém tem quaisquer idéias interessantes sobre isso?
Solução
Você pode fazer qualquer coisa (ou quase nada) com o Delphi.Eu não recomendo o seguinte código para usar, basta saber que o truque é possível:
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;
Outras dicas
Muitas vezes, na refatoração você precisa tomar uma muito ampla vista para o código.Por "limpeza" de um par de operações como este, quando o mais provável é que você não deve fazer qualquer uma destas operações em todos os?
Neste caso, parece suspicous-me que você tem uma rotina que precisa lidar com 4 separar listas de seqüência de caracteres.Que não parece muito provável que tenha um bom nível de coesão.Talvez, em vez disso, deve ser uma seqüência de caracteres lista de rotina de tratamento chamado quatro vezes.Então, eu realmente gostaria de ver toda a rotina, em vez de comentar sobre como fazer este nit no-lo mais bonito.
Na verdade, qual é o problema com 4 construtores?
Se faz sentido em seu contexto, é possível agregar declarações dentro de um especializados 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;
Assim, você pode especializados sua lista.
Você pode criar uma série de versões sobrecarregadas com 2, 3, 4, etc.parâmetros.Por exemplo:
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.
Se eu fosse fazer isso, eu ia escrever um script para gerar o código.
Como um aparte, no meu código, eu ia escrever InitialiseNil(L1, L2)
no início da função, e FreeAndNil(L2, L1)
no manipulador de exceção. InitialiseNil
e FreeAndNil
são funções geradas por um simples script em Python que está incluído no codebase como um comentário para que ele possa ser re-executada.Uma rotina como CreareStringLists
como definido acima, só é útil se você tem uma correspondência de rotina para libertá-los todos de uma só vez.Isto permite-lhe escrever:
CreateStringLists(L1, L2);
Try
// do stuff with L1, L2
Finally
FreeAndNil(L2, L1);
End;
Finalmente, eu não estou dizendo que eu seria, necessariamente, fazer isso, mas este é entendido como um ingênuo e direta resposta para a pergunta.Como O @T. E. D.estados, a necessidade de se fazer isso sugere problemas mais profundos no codebase.