C# - Usando Expressões Lambdas com argumentos Func e Action em um método List<T>


 Neste artigo eu vou mostrar como podemos usar expressões lambdas para os delegates Func e Action usando o método List genérico.

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 para fazer isso seria manter o tipo de parâmetro e o tipo de retorno.

As expressões lambdas são funções podem conter expressões e declarações que são usadas para criar delegates e árvores de expressões onde o tipo das variáveis não precisam ser declarados visto que elas usam métodos anônimos.

Uma expressão lambda é uma função anônima que você pode usar para criar delegates ou tipos de árvore de expressão. Usando expressões lambda, você pode gravar funções locais que podem ser passadas como argumentos ou serem retornadas como o valor de chamadas de função. Expressões lambda são particularmente úteis para escrever expressões de consulta LINQ. http://msdn.microsoft.com/pt-br/library/vstudio/bb397687.aspx

Como uma expressão lambda é uma expressão ela somente pode ser usada como parte de uma instrução. Desta forma podemos declarar a expressão lambda e chamar a função passando um valor ao parâmetro:

y => y * y   
    Function(y) y * y   
Na linguagem C# todas as expressões usam o operador lambada => que significa "vá para"
C# VB .NET  

O lado esquerdo do operador lambda especifica os parâmetros de entrada (se houver) e o lado direito trata a expressão ou bloco de instruções.

A sintaxe de uma expressão lambda lembra a de uma função padrão. As diferenças são as seguintes:

- Uma expressão lambda não tem um nome.

- Expressões lambda não podem ter modificadores, como Overloads ou Overrides.

- Expressões lambda não usam uma cláusula As para designar o tipo de retorno da função. Em vez disso, o tipo é inferido do valor que o corpo da expressão lambda avalia. Por exemplo, se o corpo da expressão lamba for Where cli.City = "Brazil", seu tipo de retorno é Boolean.

- O corpo da função deve ser uma expressão, não uma instrução. O corpo pode consistir de uma chamada para um procedimento de função, mas não uma chamada para um procedimento sub.

- Nas expressões lambadas não existe uma instrução Return. O valor retornado pela função é o valor da expressão no corpo da função.

- Ou todos os parâmetros devem ter tipos de dados especificados ou todos devem ser inferidos.

- Parâmetros opcionais e ParamArray não são permitidos.

- Parâmetros genéricos não são permitidos.

Como resultado dessas restrições e das maneiras pelas quais as expressões lambda são usadas, elas geralmente são simples , curtas e pouco complexas.

As listas genéricas são muito usadas devido a sua versatilidade e eficiência sendo uma ótima maneira de armazenar, recuperar e geralmente trabalhar com objetos.

A maioria dos métodos da classe List<T> tomam como argumentos os delegates Predicate, Func ou Action.

E este artigo mostra como podemos usar expressões lambdas com o método List<T> que tomam como argumentos Func e Action.

Recordando a definição dos delegates Func e Action temos que:

Recursos usados :

Criando o projeto base no VS 2013

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 List_Func_Action e clique no botão OK;

A seguir no  meu PROJECT clique em Add Class e informe o nome Inventario definindo o código conforme abaixo:

   public class Inventario
   {
        public int Id { get; set; }
        public int Estoque { get; set; }
        public double Preco { get; set; }
   }

E vamos criar uma lista de itens no inventário definindo o método CriaListaInventario() conforme código a seguir:

public static List<Inventario> CriaListaInventario()
{
            List<Inventario> listaInventario = new List<Inventario>();
            listaInventario.Add(new Inventario { Id = 1, Estoque = 5, Preco = 1.99 });
            listaInventario.Add(new Inventario { Id = 2, Estoque = 5, Preco = 2.09 });
            listaInventario.Add(new Inventario { Id = 3, Estoque = 5, Preco = 0.75 });
            listaInventario.Add(new Inventario { Id = 4, Estoque = 5, Preco = 4.25 });
            listaInventario.Add(new Inventario { Id = 5, Estoque = 5, Preco = 5.60 });
            listaInventario.Add(new Inventario { Id = 6, Estoque = 5, Preco = 2.15 });
            return listaInventario;
}

Usando métodos de List<> com argumentos Func e Action

Existem muitos métodos List<> que utilizam um tipo Func como argumento. Antes de mostrarmos, lembre-se que o delegate Func usa parâmetros e retorna um tipo, por isso sua utilização vai depender do método de List<T> e da assinatura do delegate Func, visto que este delegate pode tomar até 16 parâmetros.

Um dos métodos mais úteis de List<> é na verdade um método de extensão para Enumerable chamado Where.

Este método permite obter um subconjunto de uma lista conforme o delegate Func Where especificado.

Vamos definir o método  EncontrarItensComCustoMenorFunc conforme abaixo o código onde comparamos o preço de cada item com o preço informado e retornamos uma lista de de itens usando ToList:

   public static List<Inventario> EncontrarItensComCustoMenorFunc(double custoUnitario)
   {
            Func<Inventario, bool> WhereFunc = delegate(Inventario item)
            {
                return item.Preco < custoUnitario;
            };
            return lista.Where(WhereFunc).ToList<Inventario>();
   }

A seguir vamos simplificar o código acima usando uma expressão lambda :

   public static List<Inventario> EncontrarItensComCustoMenorFunc(double custoUnitario)
   {
         return lista.Where(item => item.Preco < custoUnitario).ToList<Inventario>();
   }

Agora podermos exibir cada item da lista obtida vamos usar o método ForEach da lista que usa um delegate Action() como parâmetro.

Lembrando a definição, temos que:

public void Each<T>(IEnumerable<T> items, Action<T> action)
{
    foreach (var item in items)
        action(item);
}

Logo podemos usar o seguinte código para iterar sobre cada item e imprimir as informações :


EncontrarItensComCustoMenorFunc(3.99).
ForEach(i => Console.WriteLine("ID = " + i.Id + " Estoque= " + i.Estoque + " Preço= " + i.Preco));

 

O código completo é dado abaixo:

using System;
using System.Collections.Generic;
using System.Linq;

namespace List_Func_Action
{
    class Program
    {
        static List<Inventario> lista;
        static void Main(string[] args)
        {
            lista = CriaListaInventario();

            EncontrarItensComCustoMenorFunc(3.99).ForEach(i => Console.WriteLine("ID = " + i.Id + " Estoque= " + i.Estoque + " Preço= " + i.Preco));

            Console.ReadKey();
        }

         public static List<Inventario> EncontrarItensComCustoMenorFunc(double custoUnitario)
        {
                return lista.Where(item => item.Preco < custoUnitario).ToList<Inventario>();
        }

        public static List<Inventario> CriaListaInventario()
        {
            List<Inventario> listaInventario = new List<Inventario>();
            listaInventario.Add(new Inventario { Id = 1, Estoque = 5, Preco = 1.99 });
            listaInventario.Add(new Inventario { Id = 2, Estoque = 3, Preco = 2.09 });
            listaInventario.Add(new Inventario { Id = 3, Estoque = 4, Preco = 0.75 });
            listaInventario.Add(new Inventario { Id = 4, Estoque = 8, Preco = 4.25 });
            listaInventario.Add(new Inventario { Id = 5, Estoque = 7, Preco = 5.60 });
            listaInventario.Add(new Inventario { Id = 6, Estoque = 9, Preco = 2.15 });
            return listaInventario;
        }
    }
}

Os seguintes métodos de List<T> também usam um argumento do tipo Func :

Para ver a lista completa acesse o link :  http://msdn.microsoft.com/en-us/library/s6hkc2c4.aspx

Pegue o exemplo do projeto aqui:  List_Func_Action.zip

Porque do céu se manifesta a ira de Deus sobre toda a impiedade e injustiça dos homens, que detêm a verdade em injustiça.
Porquanto o que de Deus se pode conhecer neles se manifesta, porque Deus lho manifestou.
Porque as suas coisas invisíveis, desde a criação do mundo, tanto o seu eterno poder, como a sua divindade, se entendem, e claramente se vêem pelas coisas que estão criadas, para que eles fiquem inescusáveis;

Romanos 1:18-20

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:


José Carlos Macoratti