[Delphi] 3 formas de percorrer uma lista

[Delphi] 3 formas de percorrer uma lista

Saudações, leitores!
Nas versões mais antigas do Delphi (como a bem conhecida versão 7), sempre que era necessário percorrer uma lista, utilizávamos uma variável do tipo integer como contador, correto? No entanto, alguns programadores que migraram para as versões mais recentes do Delphi não conhecem algumas alternativas para essa codificação. As dicas desse artigo são simples, porém, podem despertar o interesse de programadores que ainda utilizam contadores. Vamos lá!

 

Esse artigo é uma homenagem ao André Oliveira, que sempre orienta e recomenda melhores técnicas de programação através dos recursos que a linguagem fornece.

É bastante comum, em nossas codificações, percorrer listas para executar um processamento, como em itens de uma TListBox, campos de um DataSet ou componentes de um formulário. Neste artigo, optei por exemplificar uma lista de objetos com Generics. Considere a seguinte classe:

type
  TPessoa = class
  private
    FNome: string;
  public
    constructor Create(const Nome: string);
    property Nome: string read FNome write FNome;
  end;
 
implementation  
 
{ TPessoa }
 
constructor TPessoa.Create(const Nome: string);
begin
  FNome := Nome;
end;

Nada de especial. A classe possui um campo private preenchido no constructor e manipulado através de uma propriedade. Como o exemplo é didático, suspendi a criação de Getters e Setters.

Na nossa aplicação, imagine que seja necessário trabalhar com uma lista de objetos do tipo TPessoa.

var
  Lista: TObjectList<TPessoa>;

Com essa situação delimitada, apresentarei três formas de iterar essa lista pelos seguintes motivos:

  • Sair do paradigma de que só existe contadores;
  • Apresentar os recursos presentes nas versões mais recentes do Delphi;
  • Manter o código mais limpo e/ou expressivo.

 

1) Com contador
Bom, não preciso explicar muito, não é? 🙂
A primeira forma consiste em utilizar uma variável numérica como contador da lista, acessando os itens pelo índice da iteração atual. Muitos programadores utilizam essa forma por ser, podemos dizer, “tradicional”.

var
  Lista: TObjectList<TPessoa>;
  Contador: integer;
begin
  Lista := TObjectList<TPessoa>.Create;
 
  Lista.Add(TPessoa.Create('Walter White'));
  Lista.Add(TPessoa.Create('Frank Underwood'));
  Lista.Add(TPessoa.Create('Jack Bauer'));
 
  for Contador := 0 to Pred(Lista.Count) do
    ShowMessage(Lista[Contador].Nome);
 
  Lista.Free;
end;

Apenas a título de observação, notaram a presença do Pred? Essa função decrementa um número, substituindo, portanto, o “Count – 1”.

 

2) Com a estrutura for-in
Depois que publiquei o artigo sobre a cópia de registros de um DataSet, algumas pessoas ficaram surpresas com o for-in no Delphi, principalmente pelo fato de que essa estrutura não existe na versão 7. Pois bem, o for-in pode ser interpretado como “para cada X em Y, faça…”, semelhante ao foreach do C# e Java.

var
  Lista: TObjectList<TPessoa>;
  Pessoa: TPessoa;
begin
  Lista := TObjectList<TPessoa>.Create;
 
  Lista.Add(TPessoa.Create('Walter White'));
  Lista.Add(TPessoa.Create('Frank Underwood'));
  Lista.Add(TPessoa.Create('Jack Bauer'));
 
  for Pessoa in Lista do
    ShowMessage(Pessoa.Nome);
 
  Lista.Free;
end;

 

3) Com um Enumerator
Este é um recurso que poucos conhecem. Com Enumerators, não há contadores ou estruturas for-in. É necessário utilizar uma estrutura while, acessando o item da iteração atual pela propriedade Current:

var
  Lista: TObjectList<TPessoa>;
  Itens: TEnumerator<TPessoa>;
begin
  Lista := TObjectList<TPessoa>.Create;
 
  Lista.Add(TPessoa.Create('Walter White'));
  Lista.Add(TPessoa.Create('Frank Underwood'));
  Lista.Add(TPessoa.Create('Jack Bauer'));
 
  Itens := Lista.GetEnumerator;
  while Itens.MoveNext do
    ShowMessage(Itens.Current.Nome);
 
  Lista.Free;
end

O diferencial do Enumerator é a abstração ao trabalhar com a lista. A função GetEnumerator, por exemplo, responde a tipos genéricos, dispensando a necessidade de typecasts. Além disso, ao pressionar Ctrl + Espaço em Current, observe também que o Code Completion já exibe a propriedade como tipo TPessoa:

Property Current do Enumerator

 

No caso de uma TListBox ou similares que possuem uma lista de itens do tipo TStrings, a sintaxe é ligeiramente diferente por não se tratar de Generics. Neste caso, utilizamos o TStringsEnumerator:

var
  Itens: TStringsEnumerator;
begin
  Itens := ListBox1.Items.GetEnumerator;
  while Itens.MoveNext do
    ShowMessage(Itens.Current);
end;

 

Conhece outra forma de percorrer uma lista? Compartilhe conosco nos comentários!
Até breve, pessoal!


 

Compartilhe!
Share on FacebookTweet about this on TwitterShare on LinkedInShare on Google+Pin on PinterestEmail this to someone

12 comentários

  1. Parabéns André, show, esperamos que você sempre continue compartilhando seus conhecimentos e experiencia conosco, seus artigos não só me ajudou muito como tenho certeza que deve ajudar muitos outros programadores de todos os níveis.
    Abraço.

    1. Obrigado, Daniel!
      Sinto-me grato ao ler comentários como o seu. Pretendo continuar este trabalho por muito, muito tempo! 🙂
      Agradeço a você também pelo apoio!
      Abraço!

  2. Parabéns André… conhecimento represado não é uma boa prática… quando esse é compartilhado todos ganham.
    Excelente didática… Direto ao ponto.

  3. Bom dia, gostei deste artigo, não conhecia essas maneiras alternativas de percorrer lista ou objetos.
    Mais um pouco de conhecimento adquirido…
    Obrigado!

    1. Esse é o objetivo, Fábio: compartilhar essas alternativas e os recursos relativamente desconhecidos do Delphi.
      Obrigado pelo comentário e continue acompanhando o blog! Abraço!

  4. São pessoas assim como você, André, que fazem a diferença! Conhecimento é poder! E compartilhá-los é de uma atitude muito nobre! Obrigada!

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Preencha o campo abaixo * Time limit is exhausted. Please reload CAPTCHA.