C# Tips & Tricks - Métodos ForEach

É comum criarmos loops for each em nosso código para realizarmos uma determinada ação nos items de uma lista ou array. Alguns desenvolvedores não sabem que desde a versão 2.0 do .NET Framework existem métodos que simplificam bastante essa abordagem.

Vamos criar uma classe simples para utilizarmos posteriormente no código.

public class Customer
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string EmailAddress { get; set; }

    public override string ToString()
    {
        return string.Format("{0} {1}\nEmail: {2}", FirstName, LastName, EmailAddress);
    }
}

Essa classe representa um cliente que possui um nome, sobrenome e e-mail. Além disso, sobrescreve o método ToString de System.Object e utiliza propriedades automáticas (C# 3.0).

Vamos agora criar uma lista genérica de clientes.

var lista = new List<Customer>
{
    new Customer { FirstName = "Ari", LastName = "Raimundo", EmailAddress = "ari@mail.com"},
    new Customer { FirstName = "Anders", LastName = "Hejlsberg", EmailAddress = "anders@mail.com"},
    new Customer { FirstName = "Bill", LastName = "Gates", EmailAddress = "bill@mail.com"},
    new Customer { FirstName = "Jesse", LastName = "Liberty", EmailAddress = "jesse@mail.com"}
};

Digamos que queremos alterar o sobrenome de todos os clientes para letras maiúsculas. O código abaixo seria o caminho mais comum.

foreach (var c in lista)
    c.LastName = c.LastName.ToUpper();

O que poucos conhecem é que a classe List possui o seguinte método.

public void ForEach(Action<T> action);

O método ForEach realiza a ação especificada pelo parâmetro action em todos os itens da lista. O parâmetro action é do tipo System.Action<T>, ou seja, encapsula um método que não retorna valor e possui um parâmetro que é o item da lista.

Podemos substituir o loop então da seguinte forma:

lista.ForEach(c => { c.LastName = c.LastName.ToUpper(); });

Estou usando uma expressão lambda para representar o parâmetro action. O range dessa expressão seria a variável c, que é do tipo Customer.

Vamos modificar o código um pouco para mostrar os clientes na tela de console.

lista.ForEach(c =>
{
    c.LastName = c.LastName.ToUpper();
    Console.WriteLine(c);
});

Simples não é? Agora vamos fazer o mesmo com o array do código abaixo.

var array = new Customer[]
{
    new Customer { FirstName = "Ari", LastName = "Raimundo", EmailAddress = "ari@mail.com"},
    new Customer { FirstName = "Anders", LastName = "Hejlsberg", EmailAddress = "anders@mail.com"},
    new Customer { FirstName = "Bill", LastName = "Gates", EmailAddress = "bill@mail.com"},
    new Customer { FirstName = "Jesse", LastName = "Liberty", EmailAddress = "jesse@mail.com"}
};

A diferença agora é que iremos utilizar um método estático da classe System.Array. Esse método tem dois parâmetros: o array e a ação a ser executada em seus itens.

public static void ForEach<T>(T[] array, Action<T> action);

Para fazer o loop e mostrarmos os clientes na tela de console utilizamos o código abaixo.

Array.ForEach(array, c =>
{
    c.LastName = c.LastName.ToUpper();
    Console.WriteLine(c);
});

Bom, você deve estar se perguntando: qual a diferença? Existe diferença de performance? Bom, não fiz nenhum teste, vejam o link abaixo e tirem suas próprias conclusões.

Performance of foreach vs. List.ForEach
http://bit.ly/5VKDrD

Particularmente, sugiro que utilizem esses métodos.

Um comentário:

  1. Valewwwww Ari,

    tava um dia e meio quebrando a cabeça com o obj LinQ a proposta acima resolveu o problema.

    Obrigado

    ResponderExcluir