C#  - Chamando métodos em tempo de execução


Hoje veremos como podemos decidir qual método chamar em tempo de execução  na linguagem C#.

Saber trabalhar com delegates e eventos é ter acesso aos blocos fundamentais sobre os quais a camada GUI opera, sendo uma forma de dissociar várias partes do seu código.

Os delegates tem como fundamento realizar duas tarefas:

1- Quando criado, um delegate aponta para um método (instância ou estática) em um contêiner (classe ou estrutura). Para eventos, ele aponta para um método manipulador de eventos.

2- Um delegate define exatamente o tipo de método para o qual pode apontar, incluindo o número e os tipos de parâmetros e também o tipo de retorno.

Você pode criar uma instância do delegate apontando para um método. Então, toda vez que você chama o delegate, ele chama o método para você. Se o método retornar um valor, o delegate vai retornar o valor para você.

Além disso podemos definir os delegates em tempo de execução, e, isso adiciona flexibilidade ao nosso código. Podemos atribuir métodos à medida que nosso aplicativo está sendo executado com base nos valores atuais das variáveis.

Para ilustar veremos um exemplo prático onde vamos chamar métodos em tempo de execução usando delegates.

Neste exemplo vamos declarar um delegate que vai corresponder a assinatura dos métodos de destino, aproveitando o recurso dos delegates de se comportarem como um ponteiro seguro para funções. Você vai perceber que os delegates podem ser agregados e armazenados como qualquer outro dado e então podem ser executados.

Criando um projeto Console .Net Core

No Visual Studio 2019 Community crie um projeto do tipo Console para .NET Core chamado CShp_Runtime1:

Vamos criar um programa simples que realiza as 4 operações matemáticas : somar, subtrair, dividir e multiplicar.

Para isso vamos criar 4 métodos estáticos :

        static double Dividir(double a, double b)
        {
            return a / b;
        }

        static double Multiplicar(double a, double b)
        {
            return a * b;
        }

        static double Somar(double a, double b)
        {
            return a + b;
        }

        static double Subtrair(double a, double b)
        {
            return a - b;
        }

Agora vamos criar um delegate genérico do tipo T que vai representar cada operação matemática:


 delegate T OperacoesMatematicas<T>(T a, T b);
 

Na sequência, para poder armazenar as operações matemáticas, vamos criar uma lista deste delegate:


List<OperacoesMatematicas<double>> listaOperacoes = new List<OperacoesMatematicas<double>>();
 

Observe que aqui já definimos o tipo double com o qual vamos operar que corresponde à assinatura dos métodos que definimos para realizar as operações.

E agora podemos armazenar cada método criado na lista de delegates. Após isso cada delegate irá apontar para um método:


 
listaOperacoes.Add(Somar);
  listaOperacoes.Add(Dividir);
  listaOperacoes.Add(Subtrair);
  listaOperacoes.Add(Multiplicar);
 

Agora basta percorrer a lista de delegates e executar as operações:

double resultado = 0.0;

foreach (OperacoesMatematicas<double> operacao in listaOperacoes)
{
    resultado = operacao(6, 3);
    Console.WriteLine($"{operacao.Method.Name} = {resultado}");
}
Console.ReadKey();

Executando o projeto teremos o resultado abaixo:

A seguir o código completo do projeto:

using System;
using System.Collections.Generic;
namespace CShp_Runtime1
{
    class Program
    {
        delegate T OperacoesMatematicas<T>(T a, T b);

        static void Main(string[] args)
        {
            List<OperacoesMatematicas<double>> listaOperacoes = new List<OperacoesMatematicas<double>>();
            listaOperacoes.Add(Somar);
            listaOperacoes.Add(Dividir);
            listaOperacoes.Add(Subtrair);
            listaOperacoes.Add(Multiplicar);            
            double resultado = 0.0;
            foreach (OperacoesMatematicas<double> operacao in listaOperacoes)
            {
                resultado = operacao(6, 3);
                Console.WriteLine($"{operacao.Method.Name} = {resultado}");
            }
            Console.ReadKey();
        }
        static double Dividir(double a, double b)
        {
            return a / b;
        }
        static double Multiplicar(double a, double b)
        {
            return a * b;
        }
        static double Somar(double a, double b)
        {
            return a + b;
        }
        static double Subtrair(double a, double b)
        {
            return a - b;
        }
    }
}

O código é simples, os conceitos são básicos mas você tem que conhecer e saber trabalhar com esse recurso na 'ponta da língua'

"Portanto, agora nenhuma condenação há para os que estão em Cristo Jesus, que não andam segundo a carne, mas segundo o Espírito."
Romanos 8:1

Referências:


José Carlos Macoratti