C# – Usando expressões lambdas para implementar delegates – Parte 01
Neste artigo, veja mostrar como podemos usar expressões lambdas para implementar delegates na linguagem C#.
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 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 seguir fazendo seria manter o tipo de parâmetro e o tipo de retorno.
Recursos usados :
- Visual Studio 2013 for Windows desktop
Um delegate descreve a assinatura da função que você deseja passar para o seu programa. Vamos usar como exemplo a 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 e resolvê-la 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 fórmula para calcular a raiz quadrada vamos usar 3 métodos anônimos.
Nota: A fórmula de Bhaskara é definida como : ![]()
- O primeiro método anônimo irá calcular o discriminante (
) que será usado para definir as raízes; - O segundo método anônimo irá calcular a primeira raiz (se houver);
- O terceiro método anônimo irá calcular a segunda raiz (se houver);
Nesta abordagem vemos que nenhum delegate está 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 e usando a linguagem C# com o nomeEquacaoSegundoGrau_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, criar métodos anônimos é essencialmente uma forma de passar um bloco de código como um parâmetro delegate. Ao usar 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









