C# - Usando expressões lambdas para implementar delegates - I


 Neste artigo eu vou mostrar como podemos usar expressões lambdas para implementar delegates na linguagem C#. Vamos implementar o cálculo da raiz quadrada de segundo grau usando métodos anônimos e mostrar como simplificar o código usando expressões lambdas e delegates como Func<T>.

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.

Recursos usados :

Definindo delegates com métodos anônimos

Um delegate descreve a assinatura da função que você deseja passar para o seu programa. Vamos usar como exemplo o resolução de uma equação do segundo grau usando a fórmula de Bhaskara.

Para obter as raízes de uma equação do segundo grau precisamos passar 3 parâmetros.

Vamos então definir a equação resolver uma equação do segundo grau usando delegates da seguinte forma:

delegate double EquacaoSegundoGrauDelegate(double a, double b, double c)

Observe que um delegate difere de uma função tradicional da linguagem C# pois você precisa criar uma instância do delegado e a respectiva função. Esta função pode tomar a forma de um método existente em sua classe ou pode ser um método anônimo.

Um método anônimo define o delegate sem requerer que o método já exista previamente pois nele você apenas define a implementação quando você estiver criando a instância do delegate.

Na nossa primeira implementação da formula para calcular a raiz quadrada vamos usar 3 métodos anônimos.

Nota: A fórmula de Bhaskara é definida como :

  1. O primeiro método anônimo irá calcular o discriminante () que será usado para definir as raízes;
  2. O segundo método anônimo irá calcular a primeira raiz (se houver);
  3. O terceiro método anônimo irá calcular a segunda raiz (se houver);

Nesta abordagem temos que nenhum delegate esta implementando a fórmula mas apenas criando as implementações necessárias para serem executadas com os parâmetros a, b e c.

Vamos criar um projeto usando Visual Studio 2013 for Windows Desktop do tipo Console Application usando a linguagem C# com o nome EquacaoSegundoGrau_Delegate_Lambda.

Abaixo temos as implementações dos delegates usando métodos anônimos com 3 exemplos de cálculos feitos :

 static void Metodo1()
  {
            Console.WriteLine("Método #1");

            // cria um método anônimo para calcular o discriminante
            EquacaoSegundoGrauDelegate discriminante = delegate(double a, double b, double c) { return (b * b - 4d * a * c); };

            // cria métodos anônimos para calcular as raízes da equação
            EquacaoSegundoGrauDelegate raiz1 = delegate(double a, double b, double c) { return (-b + Math.Sqrt(discriminante(a, b, c))) / (2 * a); };
            EquacaoSegundoGrauDelegate raiz2 = delegate(double a, double b, double c) { return (-b - Math.Sqrt(discriminante(a, b, c))) / (2 * a); };

            // calcula as raizes para : x^2 + 5x + 6 usando a implementação das instâncias dos delegates
            double valor1 = raiz1(1d, 5d, 6d);
            double valor2 = raiz2(1d, 5d, 6d);
            //resultado
            Console.WriteLine("Para a equação:  x^2 + 5x + 6 : As raízes são {0}, {1}", valor1, valor2);
            // calcula as raizes para : x^2 + 10x + 24
            double valor3 = raiz1(1d, -10d, 24d);
            double valor4 = raiz2(1d, -10d, 24d);
            // resultado
            Console.WriteLine("Para a equação : x^2 - 10x + 24 : As raízes são {0}, {1}", valor3, valor4);
            // calcula as raizes para : x^2 + 8x + 16
            double valor5 = raiz1(1d, 8d, 16d);
            double valor6 = raiz2(1d, 8d, 16d);
            // resultado
            Console.WriteLine("Para a equação : x^2 + 8x + 16 : As raízes são {0}, {1}", valor5, valor6);
            Console.ReadLine();
 }

Observe que nossa implementação é bem ingênua e não atende a todas possibilidades de equações do segundo grau. Pois nosso objetivo é mostrar a utilização dos métodos anônimos nos delegates. Assim temos as seguintes implementações usando métodos anônimos :

  EquacaoSegundoGrauDelegate discriminante = delegate(double a, double b, double c)
  {

    
 return (b * b - 4d * a * c);
  };
 Implementação do cálculo discriminante
  EquacaoSegundoGrauDelegate raiz1 = delegate(double a, double b, double c)
  {
    
return (-b + Math.Sqrt(discriminante(a, b, c))) / (2 * a);
  };
 Cálculo da primeira raiz
  EquacaoSegundoGrauDelegate raiz2 = delegate(double a, double b, double c)
  {

    return (-b - Math.Sqrt(discriminante(a, b, c))) / (2 * a);

  };
  Cálculo da segunda raiz

Os métodos anônimos estão definidos e destacados na cor vermelha.

Assim temos que criar métodos anônimos é essencialmente uma forma de passar um bloco de código como um parâmetro delegate.  Usando os métodos anônimos reduzimos a quantidade de código necessária para instanciar delegates porque você não precisará criar um método separado. Foi o que fizemos no exemplo acima. (Atenção : O escopo dos parâmetros de um método anônimo é o bloco do método anônimo )

A seguir  temo o código completo da implementação e o resultado da sua execução :

using System;

namespace EquacaoSegundoGrau_Delegate_Lambda
{
    class Program
    {
     
  delegate double EquacaoSegundoGrauDelegate(double a, double b, double c);

        static void Main(string[] args)
        {
            Console.WriteLine("------------------------------------------------------------------------");
            Console.WriteLine("Cálculo das raízes da equação do segundo grau pela fórmula de Bhaskara");
            Console.WriteLine("Usando delegates e métodos Anônimos");
            Console.WriteLine("------------------------------------------------------------------------");
            Metodo1();
            Console.WriteLine("------------------------------------------------------------------------");
            Console.ReadKey();
        }

        static void Metodo1()
        {
            Console.WriteLine("Método #1");

            // cria um método anônimo para calcular o discriminante
           
EquacaoSegundoGrauDelegate discriminante = delegate(double a, double b, double c) { return (b * b - 4d * a * c); };

            // cria métodos anônimos para calcular as raízes da equação
            EquacaoSegundoGrauDelegate raiz1 = delegate(double a, double b, double c) { return (-b + Math.Sqrt(discriminante(a, b, c))) / (2 * a); };
            EquacaoSegundoGrauDelegate raiz2 = delegate(double a, double b, double c) { return (-b - Math.Sqrt(discriminante(a, b, c))) / (2 * a); };

            // calcula as raizes para : x^2 + 5x + 6 usando a implementação das instâncias dos delegates
            double valor1 = raiz1(1d, 5d, 6d);
            double valor2 = raiz2(1d, 5d, 6d);
            //resultado
            Console.WriteLine("Para a equação:  x^2 + 5x + 6 : As raízes são {0}, {1}", valor1, valor2);
            // calcula as raizes para : x^2 + 10x + 24
            double valor3 = raiz1(1d, -10d, 24d);
            double valor4 = raiz2(1d, -10d, 24d);
            // resultado
            Console.WriteLine("Para a equação : x^2 - 10x + 24 : As raízes são {0}, {1}", valor3, valor4);
            // calcula as raizes para : x^2 + 8x + 16
            double valor5 = raiz1(1d, 8d, 16d);
            double valor6 = raiz2(1d, 8d, 16d);
            // resultado
            Console.WriteLine("Para a equação : x^2 + 8x + 16 : As raízes são {0}, {1}", valor5, valor6);
            Console.ReadLine();
        }
    }
}

Resultado obtido pela execução do código acima:

Podemos melhorar o nosso exemplo usando expressões lambdas e faremos isso na segunda parte deste artigo. Aguarde...

Pegue o exemplo do projeto aqui:  EquacaoSegundoGrau_Delegate_Lambda.zip

Ora, àquele que é poderoso para fazer tudo muito mais abundantemente além daquilo que pedimos ou pensamos, segundo o poder que em nós opera,
A esse glória na igreja, por Jesus Cristo, em todas as gerações, para todo o sempre. Amém
Efésios 3:20-21

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