C# - Usando expressões lambdas para os argumentos Predicate, Func e Action em listas genéricas
Neste artigo eu vou mostrar como usar expressões lambdas para argumentos Predicate, Func e Action em listas genéricas usando a linguagem C#. |
Para você poder acompanhar e entender este artigo você tem que saber o que é um delegate. Se você tem dúvidas leia o meu artigo : C# - Delegates e Eventos : Conceitos básicos e depois prossiga na leitura.
Eu não vou entrar em detalhes sobre o que é um delegate (para detalhes leia o artigo) vou apenas apresentar a sua definição (uma delas):
Um Delegate é um ponteiro para um método. Um Delegate pode ser passado como um parâmetro para um método. Podemos mudar a implementação do método dinamicamente em tempo de execução, a única coisa que precisamos seguir fazendo isso seria manter o tipo de parâmetro e o tipo de retorno. |
Sugiro também que leia os artigos sobre os delegates Predicate, Func e Action já publicados no site. (veja as referências)
Recursos usados :
Conceitos Básicos
As listas genéricas
são uma ótima maneira de armazenar, recuperar e geralmente trabalham com
objetos. A maioria dos métodos em uma classe de lista genérica toma como
argumentos tanto um Predicate, uma Func ou uma Action e isso pode confundir quem
esta iniciando na linguagem.
Neste artigo eu mostro como usar esses recursos de forma a tornar o seu código
mais elegante usando expressões lambda para todos esses três tipos de
argumentos.
Apenas para recordar vejamos as definições desses 3 delegates :
Assim em uma lista genérica esses argumentos permitem ao desenvolvedor executar um método para cada um dos itens na lista genérica.
Preparando o ambiente
Abra o VS Express 2013 for Windows Desktop e clique em New Project;
A seguir selecione a linguagem Visual C# e o template Console Application;
Informe o nome GenericList_Argumentos_Delegates e clique no botão OK;
A seguir no meu PROJECT clique em Add Class e informe o nome Estoque definindo o código conforme abaixo:
namespace GenericList_Argumentos_Delegates
{
public class Estoque
{
public int Id { get; set; }
public string Item { get; set; }
public int QuantidadeEmEstoque { get; set; }
public double PrecoUnitario { get; set; }
public Estoque(int Codigo, string Nome, int Quantidade, double Preco)
{
Id = Codigo;
Item = Nome;
QuantidadeEmEstoque = Quantidade;
PrecoUnitario = Preco;
}
}
}
|
Nossa classe Estoque possui 4 propriedades e um construtor que iremos usar para criar uma lista genérica de itens em estoque.
A seguir na classe Program vamos definir a criação da lista através do método preencheLista() e a sua exibição pelo método exibeLista() conforme o código a seguir:
namespace GenericList_Argumentos_Delegates
{
class Program
{
public static List<Estoque> _listaInventario = new List<Estoque>();
static void Main(string[] args)
{
preencheLista();
exibeLista();
Console.ReadKey();
}
static void preencheLista()
{
Estoque estq = new Estoque(1,"Caneta", 10, 1.75);
_listaInventario.Add(estq);
_listaInventario.Add(new Estoque(2, "Lapis", 30, 2.45));
_listaInventario.Add(new Estoque(3, "Clipes", 10, 3.30));
_listaInventario.Add(new Estoque(4, "Caderno", 20, 4.35));
_listaInventario.Add(new Estoque(5, "Livro", 11, 9.05));
_listaInventario.Add(new Estoque(6, "Estojo", 9, 6.45));
_listaInventario.Add(new Estoque(7, "Regua", 15, 1.45));
_listaInventario.Add(new Estoque(8, "Papel", 23, 5.50));
_listaInventario.Add(new Estoque(9, "Grampos", 8, 6.15));
_listaInventario.Add(new Estoque(10, "Grafite", 12, 1.45));
}
static void exibeLista()
{
Console.WriteLine("Lista de itens do estoque");
foreach (Estoque estq in _listaInventario.ToList())
Console.WriteLine(estq.Id + "\t" + estq.Item + "\t" + estq.QuantidadeEmEstoque + "\t" + estq.PrecoUnitario);
}
}
}
|
Métodos de uma lista genérica com argumento Predicate
O método para localizar um item, ou método Find, da lista genérica é um exemplo de método que toma um argumento Predicate.
Antes de criar a classe Predicate vamos dar uma olhada como a localização de um item é feita de forma tradicional:
public Estoque FindEstoqueForeach(int itemId)
{
foreach (Estoque item in _listaInventario)
{
if (item.Id == itemId)
return item;
}
return null;
}
|
O código usa um laço foreach para percorrer a lista de itens e localizar o item pelo seu id.
O código funciona mas existe uma maneira melhor de realizar esta tarefa. A classe da lista genérica já possui um método Find e o argumento para este método é a classe Predicate.
Lembre que o delegate Predicate toma parâmetros, executa o código usando os parâmetros e sempre retorna um boleano.
Na linguagem C# um delegate cria um método anônimo e este pode ser atribuído a uma variável Predicate que pode então ser passada para o método Find. Veja como fica o método usando o argumento Predicate:
public Estoque FindEstoquePredicate(int itemId)
{
Predicate<Estoque> pred = delegate(Estoque item)
{
return item.Id == itemId;
};
return _listaInventario.Find(pred);
}
|
Isto pode ser útil se você desejar armazenar o delegate para reutilizar. Agora vamos usar as expressões lambdas para simplificar o código. Veja como ficou mais enxuto:
public Estoque FindEstoque(int itemId) { return _listaInventario.Find(item => item.Id == itemId); } |
Vamos entender o código:
1- A parte esquerda representa os parâmetros para a função a serem avaliados, neste caso, o tipo Estoque;
2- O lado direito é uma expressão booleana que irá avaliar como verdade quando o método Find encontra o item com 'itemId';
3- Se o item não for encontrado, o método FindEstoque retornará null;
Além do método Find temos os seguintes métodos de uma lista genérica
que possuem um argumento Predicate:
Métodos de uma lista genérica com argumento Func
public List<Estoque> FindItemsWherePrecoMenorCustoFuncDelegate(double custoUnitario)
{
Func<Estoque, bool> whereFunc = delegate(Estoque item)
{
return item.PrecoUnitario < custoUnitario;
};
return _listaInventario.Where(whereFunc).ToList<Estoque>();
}
|
Note que para retornar uma lista de itens do estoque você precisa chamar o método ToList() pois Where retorna um IEnumerable e a consulta não é executada até que o resultado seja enumerado.
Podemos simplificar o método acima usando uma expressão lambada:
public List<Estoque> FindItemsWherePrecoMenorCustoFuncDelegate(double custoUnitario)
{
Func<Estoque, bool> whereFunc = item => item.PrecoUnitario < custoUnitario;
return _listaInventario.Where(whereFunc).ToList<Estoque>();
}
|
Uma simplificação melhor simplesmente passa a expressão lambda diretamente para o método Where conforme vemos abaixo:
public List<Estoque> FindItemsWherePrecoMenorQueCusto(double custoUnitario)
{
return _listaInventario.Where(item => item.PrecoUnitario < custoUnitario).ToList<Estoque>();
}
|
A seguir temos outros métodos de uma lista genérica que usa o argumento Func:
Métodos de uma lista genérica com argumento Action
Existe um método de uma lista genérica que toma um argumento Action. É o método ForEach que executa o código especificado para cada um dos itens na lista. (Lembre-se que o delegate Action não retorna nada.)
A seguir temos um exemplo onde estamos alterando o valor do preço para todos os itens da lista:
public void AlterarPreco(double novoPreco)
{
_listaInventario.ForEach(item => item.PrecoUnitario = novoPreco);
}
|
Da mesma forma podemos realizar qualquer operação sobre cada item da lista usando ForEach. A seguir temos um exemplo onde estamos combinando os argumentos Action, Func e Predicate para remover os itens da lista de estoque cujo código atende uma condição:
public void removeItens(int itemID) { _listaInventario.Where(item => item.Id == itemID).ToList().ForEach(item => _listaInventario.Remove(item)); }
|
Pegue o exemplo do projeto aqui: GenericList_Argumentos_Delegates.zip
Porque os judeus pedem
sinal, e os gregos buscam sabedoria;
Mas nós pregamos a Cristo crucificado, que é escândalo para os judeus, e loucura
para os gregos.
Mas para os que são chamados, tanto judeus como gregos, lhes pregamos a Cristo,
poder de Deus, e sabedoria de Deus.
1 Coríntios 1:22-24
Veja os
Destaques e novidades do SUPER DVD Visual Basic
(sempre atualizado) : clique e confira !
Quer migrar para o VB .NET ?
Quer aprender C# ??
Quer aprender os conceitos da Programação Orientada a objetos ? Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ? |
Gostou ?
Compartilhe no Facebook
Compartilhe no Twitter
Referências:
Super DVD Vídeo Aulas - Vídeo Aula sobre VB .NET, ASP .NET e C#
VB .NET - Realizando operações com List(of T) - Macoratti.net