C# – Usando expressões lambdas para implementar delegates – Parte 03
Continuando o nosso artigo anterior, eu vou mostrar como podemos usar expressões lambdas para implementar delegates na linguagem C#.
Continuando o nosso artigo anterior, 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 vou 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 e 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 seguir fazendo isso seria manter o tipo de parâmetro e o tipo de retorno.
Recursos usados: Visual Studio 2013 for Windows desktop
Reescrevendo a implementação do cálculo da equação do segundo grau usando o delegate FuncDependendo do cenário, não precisamos criar o nosso delegate, pois já existem delegates prontos que podemos pegar e usar. Este é o nosso caso, pois o nosso exemplo está usando três parâmetros e retornando um valor e para isso temos um delegate pronto chamado Func, que encapsula um método que pode possuir até 16 parâmetros e que retorna um tipo especificado pelo parâmetro TResult.
Sua assinatura possui 17 sobrecargas: Func(TResult), Func<T, TResult>, Func<T1,T2,TResult>, …..Func<T1,…..,T16,TResult>
Então, porque se dar ao trabalho de declarar um delegate e depois atribui-lo cada vez que precisamos usar a expressão lambda se podemos usar o delegate Func?
Vamos voltar ao nosso exemplo de implementação para resolver uma equação do segundo grau.
Na primeira parte do artigo, fizemos a implementação usando delegates com métodos anônimos. Na segunda parte reescrevemos nossa implementação usando expressões lambdas.
Como ficaria a nossa implementação usando expressões lambdas e o delegate Func?
O delegate EquacaoSegundoGrauDelegate não precisaria ser mais definido e seria substituído pelo delegate Func que já esta implementando na plataforma .NET, mas na implementação do cálculo do discriminante e das raízes vamos usar agora o delegate Func<> e as expressões lambdas.
Lembre-se que temos que passar 3 parâmetros (a, b, c) e temos que obter como retorno o valor da raiz.
Pela definição, o delegate Func deve declarar os parâmetros que vai usar e o valor de retorno.
Assim teremos que declarar o delegate Func com quatro parâmetros, sendo que o último é o parâmetro de retornos. Veja como ficou a nossa implementação:
<span style="color: #ff0000; font-family: 'Trebuchet MS';"><span style="font-size: large;"> Func<double,double,double,double></span></span><span style="color: #0000ff; font-family: 'Trebuchet MS'; font-size: large;"> discriminante = (a, b, c) => (b * b - 4d * a * c);</span> |
Implementação do cálculo discriminante |
Func<double,double,double,double> raiz1 = (a, b, c) => (-b + Math.Sqrt(discriminante(a, b, c))) / (2 * a); |
Cálculo da primeira raiz |
<span style="color: #ff0000; font-family: 'Trebuchet MS'; font-size: large;"> Func<double, double, double, double></span><span style="color: #0000ff; font-family: 'Trebuchet MS'; font-size: large;"> raiz2 = (a, b, c) => (-b - Math.Sqrt(discriminante(a, b, c))) / (2 * a);</span> |
Cálculo da segunda raiz |
A definição do delegate Func estão na cor vermelha.
Dessa forma, abaixo temos as implementações dos delegates usando expressões lambdas usando o delegate Func com 3 exemplos de cálculos feitos:
static void Metodo3()
{
Console.WriteLine("Método #2");
// cria um método anônimo para calcular o discriminante
Func<double,double,double,double> discriminante = (a, b, c) => (b * b - 4d * a * c);
// cria métodos anônimos para calcular as raízes da equação
Func<double,double,double,double> raiz1 = (a, b, c) => (-b + Math.Sqrt(discriminante(a, b, c))) / (2 * a);
Func<double, double, double, double> raiz2 = (a, b, c) => (-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();
}
Dessa forma, o nosso código ficou ainda mais enxuto e não houve mudança alguma na sua funcionalidade.
A seguir, temo o código completo da implementação e o resultado da sua execução:
using System;
namespace EquacaoSegundo_Grau_Func
{
class Program
{
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 expressões lambdas e o delegate Func<>");
Console.WriteLine("------------------------------------------------------------------------");
Metodo3();
Console.WriteLine("------------------------------------------------------------------------");
Console.ReadKey();
}
static void Metodo3()
{
Console.WriteLine("Método #2");
// cria um método anônimo para calcular o discriminante
Func<double,double,double,double> discriminante = (a, b, c) => (b * b - 4d * a * c);
// cria métodos anônimos para calcular as raízes da equação
Func<double,double,double,double> raiz1 = (a, b, c) => (-b + Math.Sqrt(discriminante(a, b, c))) / (2 * a);
Func<double, double, double, double> raiz2 = (a, b, c) => (-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:
Assim, mostramos como podemos usar delegates com métodos anônimos, expressões lambdas e também como usar o delegate Func, já implementado na plataforma .NET, para simplificar e melhorar o nosso código.
Pegue o exemplo do projeto aqui: EquacaoSegundoGrau_Delegate_Lambda_Func.zip










