Cria suas próprias coleções utilizando Iteration Pattern em C#

Standard

Antes de iniciarmos este artigo, é altamente recomendado que você saiba o que é, e como funciona a interface IEnumerable, localizada no namespace System.Collection. Com uma rápida explicação retirada do MSDN, podemos considerar um IEnumerable como:

“Exposes the enumerator, which supports a simple iteration over a non-generic collection.”

Ou seja, é uma interface que expõe o enumerador, e suporta uma iteração simples sobre uma coleção não genérica.

Ok, e o que seria esse “Iteration Pattern” ?

Iteration Pattern é um padrão de desenvolvimento muito utilizado em loops de repetições. É um padrão que viabiliza o acesso sequencial aos elementos de uma dada coleção, sem que seja necessário o conhecimento dos elementos subsequentes.

Em termos práticos, possui básicamente duas vantagens:

  • Além da padronização do código, permite que métodos que recebam coleções fiquem mais flexíveis, uma vez que o tipo de entrada seria um Enumerable. Deixando o código mais genérico e limpo.
  • Diferente de Lists e Arrays, o iterador mantém o item atual em memória, logo, se sua consulta vier do BD e possuir muitos registros, é possível limitar o uso da memória para apenas um único registro.

Considerando a seguinte classe:

public class Produto
{
    public string nome { get; set; }
    public decimal valor { get; set; }
    public bool ativo { get; set; }

    public override string ToString()
    {
        return String.Format("Nome: {0} - Valor: {1} - Ativo: {2} ", nome, valor.ToString("C"), ativo ? "SIM" : "NÃO");
    }
}

Vamos criar nossa classe para coleções de Produtos, vamos chama-la de ProdutoCollection, atente-se que a mesma deve implementar a interface System.Collection.IEnumerable:

class ProdutoCollection : IEnumerable
{
    Produto[] produtos;

    public ProdutoCollection(Produto[] listaProdutos)
    {
        produtos = new Produto[listaProdutos.Length];
        Array.Copy(listaProdutos, produtos, listaProdutos.Length);
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return (IEnumerator)GetEnumerator();
    }

    public ProdutoEnumerator GetEnumerator()
    {
        return new ProdutoEnumerator(produtos);
    }
}

Observe que a classe ProdutoEnumerator ainda não existe, este classe será chamada ao invocar o método GetEnumerator() passando o array de Produtos, a enumeração é realizada efetivamente dentro desta classe. Vamos cria-la:

class ProdutoEnumerator : IEnumerator
{
    Produto[] produtos;
    int indice = -1;

    public ProdutoEnumerator(Produto[] listaProdutos)
    {
        produtos = listaProdutos;
    }

    public Produto Current
    {
        get
        {
            try
            {
                return produtos[indice];
            }
            catch (IndexOutOfRangeException)
            {
                throw new InvalidCastException();
            }
        }
    }

    object IEnumerator.Current
    {
        get { return Current; }
    }

    public bool MoveNext()
    {
        indice++;
        return indice < produtos.Length;
    }

    public void Reset()
    {
        indice = -1;
    }
}

Esta classe também deve implementar a interface IEnumerable, observe que é implentado os métodos Current, MoveNext, Reset.

Agora podemos fazer algo como:

Produto[] listaProdutos = new Produto[]{
    new Produto() { nome = "Pedra", valor=10, ativo= true},
    new Produto() { nome = "Areia", valor=30, ativo= true},
    new Produto() { nome = "Tijolo", valor=60, ativo= false}
};

ProdutoEnumerator enumerator = new ProdutoCollection(listaProdutos).GetEnumerator();

while (enumerator.MoveNext())
    Console.WriteLine(enumerator.Current.ToString());

Interessante não acham?

Abs 😉

 

Leave a Reply

Your email address will not be published. Required fields are marked *