Entre as muitas novidades da versão 2005 do Delphi está o novo comando for-in-do, presente na nova Delphi Language. Como muitos já devem saber, esta variação do tradicional loop for permite percorrer todos os elementos de uma coleção sem ser necessário especificar o início e o fim da iteração. Assim, códigos de loops tornam-se mais simples de serem escritos. Compare:

Sem for-in-do

            var

                Colecao: TStringList;
          
                I: Integer;
          
             begin
          
                Colecao := ObterAlgumaColecao;
          
                for I := 0 to Colecao.Count – 1 do
          
                    ShowMessage(Colecao[I]);
        
Com for-in-do

            var

                Colecao : TStringList;

                Item : string;

            begin

                Colecao := ObterAlgumaColecao;

                for Item in Colecao do

                    ShowMessage(Item);
        

Bem mais fácil, não?

O que a maioria (ainda) não sabe, é que nem toda coleção pode ser usada com o loop for-in-do. Para usufruir desde novo recurso da Delphi Language, é necessário fazer algumas adaptações na classe que se pretende utilizar, e é isso que veremos neste artigo.

Atributos necessários

Para adaptar a classe ao novo loop, deve-se seguir os seguintes passos:

  • A classe deve ter um método, de visibilidade public, chamado GetEnumerator(). Esta função deve retornar uma classe, uma interface ou um record;
  • O tipo retornado por GetEnumerator() deve possuir um método (public) chamado MoveNext(), que deve retornar um tipo Boolean;
  • A classe, interface ou record retornado por GetEnumerator() deve conter uma propriedade pública somente-leitura chamada Current, do mesmo tipo de dado contido na coleção.
Se o tipo retornado por GetEnumerator() implementa a interface IDisposable, o compilador irá chamar o método Dispose do tipo quando o loop terminar.

Mãos à obra!

Nada como um exemplo para entendermos melhor como se implementar a teoria acima. Então, no Delphi 2005, clique em File->New->Unit – Delphi for Win32. Em seguida, digite o código abaixo:


            TMinhaArray = array of string;

 

            TMeuItem = class
          
            private
          
              Values: TMinhaArray;
          
              Index: Integer;
          
            public
          
              constructor Create;
          
              function GetCurrent: string;
          
              function MoveNext : Boolean;
          
           
          
              property Current : string read GetCurrent;
          
            end;
          
           
          
            TMinhaColecao = class
          
            public
          
              function GetEnumerator: TMeuItem;
          
            end;
            

Aqui apenas declaramos as classes que precisaremos implementar. Observe os métodos criados, com nomes compatíveis às especificações mencionadas anteriormente.

O construtor da classe TMeuItem não é necessário. Ele foi usado aqui apenas para inicializar a lista com alguns itens.

Implemente tudo com Ctrl + Shift + C. Para o único construtor existente, digite o código a seguir:


            constructor TMeuItem.Create;

            begin
            
              inherited Create;
            
              Values := TMinhaArray.Create('Borland', 'Delphi', '2005');
            
              Index  := -1;
            
            end;
        
O construtor da classe TMeuItem não é necessário. Ele foi usado aqui apenas para inicializar a lista com alguns itens.

Para o método GetCurrent, digite apenas:


            function TMeuItem.GetCurrent: string;

            begin
            
              Result := Values[Index];
            
            end;
        

E, por fim, para MoveNext:


            function TMeuItem.MoveNext: Boolean;

            begin
            
             if Index < High(Values) then
            
             begin
            
                Inc(Index);
            
                Result := True;
            
             end
            
             else
            
               Result := False;
            
            end;
        

O código acima simplesmente retorna o próximo item da coleção.

Agora, resta apenas o método GetEnumerator da classe TMinhaColecao, que é muito simples, como visto abaixo:


            { TMinhaColecao }

 

            function TMinhaColecao.GetEnumerator: TMeuItem;
            
            begin
            
              Result := TMeuItem.Create;
            
            end; 
            

Salve a unit com o nome de MinhaColecao.pas. Inicie então uma nova aplicação VCL no Delphi 2005 (File->New->VCL Forms Application – Win32), coloque um botão, declare nossa unit na cláusula uses da seção implementation e digite o código a seguir no evento OnClick do botão:


            uses MinhaColecao;

 

            {$R *.dfm}
            
             
            
            procedure TForm1.Button1Click(Sender: TObject);
            
            var
            
              Colecao: TMinhaColecao;
            
              S: string;
            
            begin
            
              Colecao := TMinhaColecao.Create;
            
              for S in Colecao do
            
                ShowMessage(S);
            
              Colecao.Free; 
            
            end;
        

Rode a aplicação e veja o loop for-in-do acessando nossa classe.

Conclusão

Como pudemos ver, é bem simples adaptar nossas próprias coleções para serem compatíveis com o novo comando for-in presente no Delphi 2005. Use-o e abuse-o em suas aplicações! Um forte abraço a todos e até o próximo artigo.