C# - Funções Anônimas : Expressões Lambdas e Métodos Anônimos


 Neste artigo eu vou apresentar os conceitos básicos da linguagem C# sobre funções anônimas, expressões lambdas e métodos anônimos.

Uma função anônima é uma declaração "in-line" ou expressão que pode ser usada sempre que um tipo de delegate é esperado. Podemos usá-las para inicializar um delegate nomeado ou passar uma função anônima em vez de um tipo de delegado nomeado como um parâmetro de método.

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.

Um Delegate é um ponteiro para um método que 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 observer para fazer isso seria manter o tipo de parâmetro e o tipo de retorno.

Existem dois tipos de de Funções Anônimas:

  1. Métodos Anônimos (Anonymous Method)

  2. Expressões Lambdas (Lambdas Expressions).

Nas versões anteriores à versão 2.0 da linguagem C#, a única maneira de declarar um delegate era usando métodos nomeados. A partir da versão 2.0, a linguagem C# introduziu os métodos anônimos e no C# 3.0 e posterior, as expressões lambdas substituem os métodos anônimos como a melhor maneira de escrever código embutido.

Uma expressão lambda é uma função anônima que pode conter expressões e instruções e pode ser usada para criar delegates ou tipos de árvore de expressão.

Todas as expressões lambdas usam o operador lambda  =>  o qual significa 'vai para'. A sintaxe geral de uma expressão lambda pode ser expressa assim:

( parâmetros de entrada ) => {expressão ou bloco de instrução};

Ex:     numero => numero % 2 == 1

Podemos ler essa expressão da seguinte forma:

O parâmetro de entrada chamado numero vai para a função anônima a qual retorna true se o parâmetro de entrada for um número ímpar.

Recursos usados :

Usando Expressões lambdas

As expressões lambdas usam uma sintaxe mais resumida, também chamada de, açucarada (sugar sintax),  permitindo escrever um código mais legível e sucinto.

Vejamos um exemplo usando a expressão lambda acima que retornar os números impares de uma lista de números :

A expressão lambda usada no código é :

List<int> impares = numeros.Where(n => n % 2 == 1).ToList();

O código obtém uma lista dos números impares que depois é percorrida por um laço foreach.

Ainda usando a expressão lambda acima poderíamos usar outra sintaxe para retornar true ou false para um número impar:

Neste código a sintaxe ficou assim:

numeros.ToList().ForEach(n => Console.WriteLine(n % 2 == 1));

O código verifica cada número da lista e retorna true se ele for impar e false se não for impar.

Método Anônimo x Expressão Lambda

Vejamos um exemplo onde vamos verificar se um nome esta em uma lista usando um método anônimo e depois usando expressão lambda:

1- Método Anônimo

namespace Metodo_Anonimo
{
    class Program
    {
        static void Main(string[] args)
        {
            List<string> nomes = new List<string> { "Yuri", "Jefferson", "Jessica", "Janice", "Miriam" };
            string resultado = nomes.Find(delegate(string nome)
                                       {
                                              return nome.StartsWith("M");
                                       });
            Console.WriteLine(resultado);
            Console.ReadKey();
        }
    }
}

2- Expressão Lambda

namespace Metodo_Anonimo
{
    class Program
    {
        static void Main(string[] args)
        {
            List<string> nomes = new List<string> { "Yuri", "Jefferson", "Jessica", "Janice", "Miriam" };

            string resultado = nomes.Find(nome => nome.StartsWith("M"));

            Console.WriteLine(resultado);
            Console.ReadKey();
        }
    }
}

O resultado obtido é o mesmo mas o  código ficou mais sucinto.

LINQ x Expressão Lambada

Agora vamos comparar a utilização de uma expressão LINQ com uma expressão lambda em um exemplo.

Neste exemplo vamos obter os números pares em um array de números inteiros usando LINQ e uma expressão lambda:

using System.Linq;
using System;
namespace LINQ_Lambda
{
    class Program
    {
        static void Main(string[] args)
        {
            // Declarando o vetor de números inteiros
            int[] numeros = { 1, 2, 3, 4, 5, 6 , 7 , 8 , 9, 10, 11, 12 };
            // usando LINQ
            var numerosPares_Linq = (from num in numeros
                         		            where (num % 2 == 0)
                         		            select num);
            foreach( int n in numerosPares_Linq)
            {
                Console.WriteLine("Pares (Linq) : " + n);
            }
            Console.ReadKey();
            // usando uma Expressão lambada
            var numerosPares_Lambda = numeros.Where(num => num % 2 == 0);
            foreach (int n in numerosPares_Lambda)
            {
                Console.WriteLine("Pares (Lambda) : " + n);
            }
            Console.ReadKey();
        }
    }
}

   

Comparando temos:

//Linq
var numerosPares_Linq = (from num in numeros
                             where (num % 2 == 0)
                             select num);
//Expressão Lambda
 var numerosPares_Lambda = numeros.Where(num => num % 2 == 0);

Com esses exemplos podemos verificar que as expressões lambdas realmente simplificam a sintaxe visto que não precisamos especificar o nome do método, seu tipo de retorno e modificador de acesso. Além disso elas tornam o código mais legível pois não temos que procurar no código a definição do método.

Pegue o exemplo do projeto aqui:  Expressao_lambda.zip

Lucas 5:31 - E Jesus, respondendo, disse-lhes: Não necessitam de médico os que estão sãos, mas, sim, os que estão enfermos;

Lucas 5:32 - Eu não vim chamar os justos, mas, sim, os pecadores, ao arrependimento.


 

Referências:


José Carlos Macoratti