Olá novamente!
Hoje recebi um email de um colega, através de uma lista de discussão de dot.net, com uma dúvida sobre a otimização de switchs. Lembrei então de já ter visto um código em C que utilizava ponteiros de funções ao invés de switchs.
Resolvi então implementar uma solução similar em C# utilizando delegates no lugar dos ponteiros de funções. O código implementa as quatro operações aritméticas básicas dados dois números reais.
Para isso, foi definida a classe Calculadora com os métodos referentes as quatro operações. Além desses métodos foram definidos outros dois, o ExecutaComSwitch, que e executa uma operação realizando um teste com switch e o ExecutaComDelegate, que recebe um delegate com a operação a ser executada.
O programa principal recebe os valores de duas variáveis reais e em seguida executa as quatro operações utilizando o método com switch e o método com delegate.
O código da aplicação (console) é o seguinte:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Switch
{
public enum TipoOperacao { Soma, Subtracao, Multiplicacao, Divisao};
public delegate double OperacaoDelegate(double a, double b);
public class Calculadora
{
public double Soma(double a, double b)
{
return a + b;
}
public double Substracao(double a, double b)
{
return a – b;
}
public double Multiplicacao(double a, double b)
{
return a * b;
}
public double Divisao(double a, double b)
{
return a / b;
}
public double ExecutaComSwitch(TipoOperacao op, double a, double b)
{
double resultado = 0;
switch (op)
{
case TipoOperacao.Soma:
resultado = this.Soma(a, b);
break;
case TipoOperacao.Subtracao:
resultado = this.Substracao(a, b);
break;
case TipoOperacao.Multiplicacao:
resultado = this.Multiplicacao(a, b);
break;
case TipoOperacao.Divisao:
resultado = this.Divisao(a, b);
break;
}
return resultado;
}
public double ExecutaComDelegate(OperacaoDelegate op, double a, double b)
{
return op(a, b);
}
}
class Program
{
static void Main(string[] args)
{
double a, b;
Calculadora calc = new Calculadora();
Console.Clear();
Console.WriteLine(“Informe o valor de A:”);
double.TryParse(Console.ReadLine(), out a);
Console.WriteLine(“Informe o valor de B:”);
double.TryParse(Console.ReadLine(), out b);
Console.WriteLine();
Console.WriteLine(“Usando switch:”);
double soma = calc.ExecutaComSwitch(TipoOperacao.Soma, a, b);
Console.WriteLine(“Soma: {0}”, soma.ToString(“#,##0.00”));
double subtracao = calc.ExecutaComSwitch(TipoOperacao.Subtracao, a, b);
Console.WriteLine(“Subtração: {0}”, subtracao.ToString(“#,##0.00”));
double multiplicacao = calc.ExecutaComSwitch(TipoOperacao.Multiplicacao, a, b);
Console.WriteLine(“Multiplicação: {0}”, multiplicacao.ToString(“#,##0.00”));
double divisao = calc.ExecutaComSwitch(TipoOperacao.Divisao, a, b);
Console.WriteLine(“Divisão: {0}”, divisao.ToString(“#,##0.00”));
Console.WriteLine();
Console.WriteLine(“Usando delegate:”);
soma = calc.ExecutaComDelegate(calc.Soma, a, b);
Console.WriteLine(“Soma: {0}”, soma.ToString(“#,##0.00”));
soma = calc.ExecutaComDelegate(calc.Substracao, a, b);
Console.WriteLine(“Subtração: {0}”, subtracao.ToString(“#,##0.00”));
soma = calc.ExecutaComDelegate(calc.Multiplicacao, a, b);
Console.WriteLine(“Multiplicação: {0}”, multiplicacao.ToString(“#,##0.00”));
soma = calc.ExecutaComDelegate(calc.Divisao, a, b);
Console.WriteLine(“Divisão: {0}”, divisao.ToString(“#,##0.00”));
Console.ReadLine();
}
}
}
using System;using System.Collections.Generic;using System.Linq;using System.Text;
namespace Switch{ public enum TipoOperacao { Soma, Subtracao, Multiplicacao, Divisao};
public delegate double OperacaoDelegate(double a, double b);
public class Calculadora { public double Soma(double a, double b) { return a + b; }
public double Substracao(double a, double b) { return a – b; }
public double Multiplicacao(double a, double b) { return a * b; }
public double Divisao(double a, double b) { return a / b; }
public double ExecutaComSwitch(TipoOperacao op, double a, double b) { double resultado = 0; switch (op) { case TipoOperacao.Soma: resultado = this.Soma(a, b); break; case TipoOperacao.Subtracao: resultado = this.Substracao(a, b); break; case TipoOperacao.Multiplicacao: resultado = this.Multiplicacao(a, b); break; case TipoOperacao.Divisao: resultado = this.Divisao(a, b); break; } return resultado; }
public double ExecutaComDelegate(OperacaoDelegate op, double a, double b) { return op(a, b); } }
class Program { static void Main(string[] args) { double a, b; Calculadora calc = new Calculadora(); Console.Clear(); Console.WriteLine(“Informe o valor de A:”); double.TryParse(Console.ReadLine(), out a); Console.WriteLine(“Informe o valor de B:”); double.TryParse(Console.ReadLine(), out b); Console.WriteLine();
Console.WriteLine(“Usando switch:”); double soma = calc.ExecutaComSwitch(TipoOperacao.Soma, a, b); Console.WriteLine(“Soma: {0}”, soma.ToString(“#,##0.00”)); double subtracao = calc.ExecutaComSwitch(TipoOperacao.Subtracao, a, b); Console.WriteLine(“Subtração: {0}”, subtracao.ToString(“#,##0.00”)); double multiplicacao = calc.ExecutaComSwitch(TipoOperacao.Multiplicacao, a, b); Console.WriteLine(“Multiplicação: {0}”, multiplicacao.ToString(“#,##0.00”)); double divisao = calc.ExecutaComSwitch(TipoOperacao.Divisao, a, b); Console.WriteLine(“Divisão: {0}”, divisao.ToString(“#,##0.00”)); Console.WriteLine();
Console.WriteLine(“Usando delegate:”); soma = calc.ExecutaComDelegate(calc.Soma, a, b); Console.WriteLine(“Soma: {0}”, soma.ToString(“#,##0.00”)); soma = calc.ExecutaComDelegate(calc.Substracao, a, b); Console.WriteLine(“Subtração: {0}”, subtracao.ToString(“#,##0.00”)); soma = calc.ExecutaComDelegate(calc.Multiplicacao, a, b); Console.WriteLine(“Multiplicação: {0}”, multiplicacao.ToString(“#,##0.00”)); soma = calc.ExecutaComDelegate(calc.Divisao, a, b); Console.WriteLine(“Divisão: {0}”, divisao.ToString(“#,##0.00”));
Console.ReadLine(); } }}