C# - Expressões Lambdas (revisitado)


 Neste artigo vamos rever os conceitos básicos das Expressões lambdas na linguagem C#.

Primeiro vamos começar revendo a definição formal de expressões lambdas.

O que é uma expressão lambda ?

Uma expressão lambda é uma função anônima que você pode usar para criar delegados ou tipos de árvore de expressão. Ao usar expressões lambda, você pode escrever funções locais que podem ser passadas como argumentos ou retornadas como o valor de chamadas de função.

Expressões lambda são particularmente úteis para escrever expressões de consulta LINQ.

Como criar um expressão lambda ?

Para criar uma expressão lambda, especifique os parâmetros de entrada (se houver) no lado esquerdo do operador lambda => e coloque a expressão ou o bloco de instruções do outro lado.

Por exemplo, a expressão lambda x => x * x especifica um parâmetro chamado x e retorna o valor de x ao quadrado.

Você pode atribuir essa expressão a um tipo delegate assim :

delegate int delegado(int i);  

static void Main(string[] args)  
{  
    delegado meuDelegate = x => x * x;  
    int valor = meuDelegate(5);  
}

Onde e porque usamos expressões lambdas ?

As expressões lambdas são usadas em consultas LINQ baseadas em métodos como argumentos para métodos de operador de consulta padrão como Where.

Assim, as expressões lambda reduzem a quantidade de trabalho necessária ao iterar com dados. Todos os dados enumeráveis são consultáveis por meio do LINQ com o uso de uma consulta semelhante às consultas SQL.

Obs: A LINQ possui um mecanismo embutido para fazer um loop através de dados enumeráveis e usar certas condições de configuração nas cláusulas where para filtrar os dados.

As expressões lambda funcionam de maneira semelhante. Alguns dos métodos de extensão existentes apresentam expressões lambda incorporadas para executar determinadas ações e facilitar a execução de trabalhos repetitivos. (Vamos ver isso mais a frente)

Nota: As expressões lambda não exigem métodos de extensão para funcionar, mas esse é o uso mais comum atualmente.

Expressões Lambdas no.NET Framework

Existe uma variedade de métodos de extensão definidos no .NET Framework que usam Expressões Lambdas.

No assembly System.Core, o namespace System.Linq apresenta duas classes estáticas contendo uma variedade de extensões para fontes IEnumerable e IQueryable.

Algumas dessas expressões são definidas no método Where, por exemplo. O método Where é definido como

Where<TSource> (IEnumerable <TSource>, Func<TSource, bool>);

Aqui temos que Func<> define uma expressão lambda, onde os parâmetros genéricos são a chave.

O primeiro parâmetro(TSource) é o tipo que está sendo avaliado na expressão lambda, e o segundo parâmetro(bool) é o valor que precisa ser retornado pelo método.

Então, como usamos as expressões do Lambda?

Em C#, a expressão lambda é definida assim :

var clientes = lista.Where (cli => cli.Nome == "Macoratti");

Neste código o operador "=>" denota uma expressão lambda.

O parâmetro "cli" é o alias ou nome para o objeto do tipo <TSource> como mostrado acima na instrução Func.

O primeiro parâmetro é o objeto sendo iterado, ou o tipo de item dos itens na coleção.

Por exemplo, se você tem uma Lista<MeuObject>, "cli" é uma referência para o tipo MeuObject. Portanto, em nossa expressão acima, o resultado (que deve ser um booleano) só recebe objetos onde o nome é "Macoratti".

Tudo à direita do operado "=>" está definindo os critérios para verificar se o método retorna verdadeiro e falso.

Então, como é usado?

A seguir temos um exemplo onde definimos um delegate Func<string,int> com expressão lambda e com delegate:

using System;
using static System.Console;
namespace ExpressaoLambda1
{
    class Program
    {
        //Expressão Lambda
        static Func<string, int> tamanhoTextExpressaoLambda = (text => text.Length);
        //Expressão Delegate
        static Func<string, int> tamanhoTextoDelegate = delegate (string text) { return text.Length; };
        static void Main(string[] args)
        {
            WriteLine("Usando Expressão Lambda");
            WriteLine(tamanhoTextExpressaoLambda("Macoratti .net quase tudo para .NET."));
            WriteLine("Usando Delegate");
            WriteLine(tamanhoTextoDelegate("Macoratti .net quase tudo para .NET."));
            ReadLine();
        }
    }
}

Ambas as declarações são funções anônimas onde temos que a expressão lambda é a sintaxe mais recente e a mais conscisa. Ambas são formas distintas de obter o mesmo resultado.

Muitos operadores de consulta padrão têm um parâmetro de entrada cujo tipo é de delegate genérico Func<T, TResult>.  Esses representantes usam parâmetros de tipo para definir o número e os tipos de parâmetros de entrada e o tipo de retorno do delegado.

Os delegados de Func são muito úteis para encapsular expressões definidas pelo usuário que são aplicadas a cada elemento em um conjunto de dados de origem.

O delegado pode ser instanciado como Func<int, bool> meuFunc, em que int é um parâmetro de entrada e bool é o valor de retorno. O valor de retorno é sempre especificado no último parâmetro de tipo.

Assim Func<int, string, bool> define um delegado com dois parâmetros de entrada, int e string, e um tipo de retorno de bool.

No código abaixo o delegado Func, quando invocado, retornará verdadeiro ou falso para indicar se o parâmetro de entrada é igual a 5:

Func<int, bool> meuFunc = x => x == 5;
bool resultado = meuFunc(4);
// retorna false

Observe que expressões lambdas (=> ) também podem ser usadas para formar Expression Lambdas, onde você cria uma Árvore de Expressões(Expression Trees) em vez de um delegado.

Isso é bom, já que você pode usar a mesma sintaxe se estiver usando o LINQ to Objects (que é baseado em delegados como Func <T, TResult>) ou LINQ to Entities (que usa IQueryable <T> e expression trees).

E estamos conversados...

'Agora é o juízo deste mundo; agora será expulso o príncipe deste mundo.
E eu, quando for levantado da terra, todos atrairei a mim.
E dizia isto, significando de que morte havia de morrer.'

João 12:31-33

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 ?

Referências:


José Carlos Macoratti