Delegates é bastante comum no cenário .NET. Sendo conhecido como objeto que referência métodos, possuem diversos benefícios como:
- Encapsulação de métodos
- Callback
- Eventos
- Programação assíncrona
- Composição de métodos
- Delegação de responsabilidade
que permite uma programação mais flexível.
Partindo desse ponto, será abordado como o “Objeto que referência métodos” realmente funciona por “debaixo dos panos” e como o compilador e o CLR trabalham para implementar o delegates.
Código:
public delegate void MeuDelegate(int valor);Ao escrever o código acima, o compilador define uma classe completa a esse exemplo:
class MyDelegate : System.MulticastDelegate
{
public MeuDelegate(Object object, Inptr method);
public virtual void Invoke(Int32 valor);
public virtual IAsyncResult BeginInvoke(Int32 valor,
AsyncCallback callback, object object);
public virtual void EndInvoke(IAsyncResult result);
}E esta classe tem quatro partes principais:
-
Construtor: Utilizado para criar uma instância do delegado, aceitando dois parâmetros: Um objeto e um ponteiro para um método.
-
Método Invoke Método utilizado para chamar o método associado ao delegado no mesmo thread.
-
Metódo BeginInvoke Método utilizado para chamar o método de forma assíncrona.
-
Método EndInvoke Método utilizado para finalizar uma chamada assíncrona feita com BeginInvoke.
Existem também três campos internos que desvendam como os métodos ( estáticos e de instância ) são apontados, sendo provavelmente a característica mais significativa nos delegates.
-
_target Se o método associado ao delegado é estático, este campo é nulo. Se for um método de instância, ele contém uma referência ao objeto que contém o método.
-
methodptr Este é um número especial que identifica o método associado ao delegado.
-
invocationlist Este campo geralmente é
nulle é usado para armazenar uma lista de delegados, geralmente quando você combina vários delegados em um único delegado.
Aqui um exemplo de como esses campos funcionam com método estático e método de instância.
MeuDelegate objetoEstatico = new MeuDelegate(Classe.MetodoStatic);
MeuDelegate objetoInstancia = new MeuDelegate(new Classe().MetodoInstancia);
Se você cria um delegado para um método estático, o campo _target é nulo e o _methodptr aponta para o método estático.

Se for um método de instância, _target aponta para o objeto que contém o método e _methodptr aponta para o método em si.
O método .Combine é usado para combinar vários delegados em um único delegado. Quando você combina delegados, o C# cria um novo objeto delegado para representar a combinação dos delegados originais.
MeuDelegate objetoEstatico = new MeuDelegate(Classe.MetodoStatic);
MeuDelegate objetoInstancia = new MeuDelegate(new Classe().MetodoInstancia);
MeuDelegate objetoListaDeDelegates = null;
objetoListaDeDelegates = (MeuDelegate) Delegate.Combine( objetoListaDeDelegates, objetoEstatico);
objetoListaDeDelegates = (MDelegate) Delegate.Combine( objetoListaDeDelegates, objetoInstancia);No exemplo dado:
objetoEstaticoé um delegado que representa um método estático.objetoInstanciaé um delegado que representa um método de instância.objetoListaDeDelegatesé inicialmente nulo, mas depois de combinar os delegados, ele representa um novo delegado que combina os métodos deobjetoEstaticoeobjetoInstancia.

Delegates Assíncronos
Os delegates em C# podem chamar métodos de forma assíncrona, o que significa que eles podem iniciar a execução de um método em um thread separado e retornar imediatamente ao thread principal.
Quando você usa o método BeginInvoke em um delegate, o CLR coloca a solicitação na fila e retorna ao thread principal. O método de destino será então chamado em um thread do pool de threads, permitindo que o thread principal execute outras tarefas enquanto aguarda a conclusão do método de destino.
O método BeginInvoke tem três parâmetros:
- O primeiro parâmetro é um parâmetro de entrada para o método.
- O segundo parâmetro é um delegado do tipo
AsyncCallBack, que é um mecanismo de retorno de chamada que será invocado quando o método de destino for concluído. - O terceiro parâmetro é usado para fornecer informações de estado assíncrono.
Se você não especificar um retorno de chamada, o método EndInvoke será usado no thread original para obter o valor de retorno do processamento assíncrono. Se um retorno de chamada estiver presente, o método EndInvoke será chamado no método de retorno de chamada.
Exemplo de código de um delegate assíncrono:
using System;
using System.Threading;
public delegate int MeuDelegado(int valor);
class Program
{
static void Main(string[] args)
{
MinhaClasse minhaClasse = new MinhaClasse();
MeuDelegado meuDelegado = new MeuDelegado(minhaClasse.MeuMetodo);
// Inicia o processamento assíncrono
IAsyncResult resultadoAssincrono = meuDelegado.BeginInvoke(5, new AsyncCallback(MeuCallback), "Informação do estado");
Console.WriteLine("Do thread principal");
Console.ReadLine();
}
public static void MeuCallback(IAsyncResult resultadoAssincrono)
{
AsyncResult resultado = (AsyncResult)resultadoAssincrono;
MeuDelegado meuDelegado = (MeuDelegado)resultado.AsyncDelegate;
int resultadoMetodo = meuDelegado.EndInvoke(resultadoAssincrono);
Console.WriteLine("Resultado do callback: " + resultadoMetodo);
// Informação do estado do thread principal
string mensagem = (string)resultadoAssincrono.AsyncState;
Console.WriteLine(mensagem);
}
}
class MinhaClasse
{
public int MeuMetodo(int valor)
{
Thread.Sleep(10000);
return (valor * valor);
}
}
Neste exemplo:
MeuDelegadoé um delegado que representa um método que retorna um inteiro e aceita um inteiro como parâmetro.MinhaClassecontém o métodoMeuMetodo, que será chamado de forma assíncrona.- O método
BeginInvokeinicia o processamento assíncrono do métodoMeuMetodo. - O método
MeuCallbacké chamado quando o métodoMeuMetodoé concluído, exibindo o resultado do callback e a informação de estado do thread principal.
Assumindo que o método MeuMetodo retorna o quadrado do valor passado como argumento, o resultado do callback será o quadrado de 5, ou seja, 25.
Portanto, a saída seria:
Do thread principal
Resultado do callback: 25
Informação do estadoDelegates é um objeto que se refere a métodos e pode ser usado tanto em processos assíncronos quanto síncronos, permitindo a execução de métodos em outras threads. O uso de processamento assíncrono é especialmente útil para realizar tarefas em segundo plano, sem bloquear o thread principal.