Clique sobre os tópicos listados abaixo para navegar até o conteúdo desejado.

  1. Básico sobre Delegate
  2. Declaração
  3. Parâmetro e retorno
  4. Delegate como parâmetro
  5. Método anônimo
  6. Método anônimo como parâmetro
  7. Vetor de delegate
  8. Retornando delegate
  9. Limitações método anônimo
  10. Delegate como atributo/propriedade de classe/struct

O tipo de dado delegate representa uma referência para um método, podendo ter parâmetros e retorno de dado. A idéia do delegate em C# é equivalente ao ponteiro para função em C e C++.

Para utilizar um delegate, precisamos declarar um tipo de delegate com parametros e tipo de retorno com posterior atribuição de um método que atenda ao que foi predefinido.

Com delegate, podemos criar métodos anônimos e utilizar os tipos de delegate Action, Func e Predicate.

Para utilizar Delegates precisamos adicionar o namespace System.

Um tipo de dado delegate é declarado utilizando a palavra reservada delegate de acordo com as sintaxes abaixo.

Sintaxe 1
modificador_acesso delegate tipo_retorno tipo_delegate();
Sintaxe 2
modificador_acesso tipo_delegate nome_delegate;
nome_delegate nome_variavel;
Sintaxe 3
nome_variavel = nome_metodo;

Na primeira sintaxe definimos um tipo de delegate com retorno. Na segunda sintaxe, a declaramos um variável tendo o novo tipo delegate como tipo de dado. Na terceira e última sintaxe, é demostrado a atribuição de um método a uma variável.

Exemplo 1
using System;
public class Program
{
    //Criação do tipo delegate
    public delegate void MeuDelegate();
   
    //Método para o tipo MeuDelegate
    public static void MeuMetodo()// static Main
    {
        //omitido
    }
	public static void Main()
	{
        //variável
	    MeuDelegate delPrint; = MeuMetodo;  

        //atribuição
        delPrint = MeuMetodo;
	}
}
Saída
-

Como delegate é uma referência para um método, esse possue as mesma características em relação à declaração de parâmetros e também retorno.

Sintaxe 1
modificador_acesso delegate tipo_retorno nome_delegate(lista_parametros);
Exemplo 2
using System;
public class Program
{
    public delegate void MeuDelegateParametro(string param);
    public delegate int MeuDelegateRetorno(int param);

    public static void MeuMetodo(string p)// static Main
    {
        Console.WriteLine(p);
    }
    //Sobrecarga
    public static int MeuMetodo(int p)// static Main
    {
        return p*2;
    }
    
	public static void Main()
	{
	    MeuDelegateParametro Print = MeuMetodo;  
	    Print("delegate C#");

        MeuDelegateRetorno Dobro = MeuMetodo;
        Console.WriteLine(Dobro(4));
	}
}
Saída
metodo anonimo como parametro
4

O uso das palavras reservadas ref e out, vistas nos conceitos de passagem por valor e referência em C# POO: Métodos, também podem ser utilizados.

Assim como em C/C++ que podem passar funções como parâmetro/argumento, C# também permite que um delegate seja utilizado da mesma forma. Abaixo a sintaxe que mostra o que foi discutido:

Sintaxe
modificador_acesso tipo_retorno nome_metodo(tipo_delegate nome_parametro);
Exemplo 3
using System;
public class Program
{
    //tipo delegate
    public delegate void TipoDelegate(string param);

    //método atribuído ao delegate
    public static void MeuMetodo(string p)// static Main
    {
        Console.WriteLine(p);
    }
    //método que recebe delegate como parâmetro
    public static void MetodoDelegate(TipoDelegate Print, string msg)// static Main
    {
        Print(msg);
    }
	public static void Main()
	{
	    TipoDelegate Print = MeuMetodo;
	    MetodoDelegate(Print,"delegate como parametro");
	}
}
Saída
delegate como parametro

Outra forma de utilizar delegates é para a criação de métodos anônimos. Esses possuem as mesma características em relação ao uso de um ou mais parâmetros, retorno e uso de ref e out.

Diferente dos delegates vistos até agora, um método anônimo não precisa ter um nome, mas precisa utilizar a palavra reservada delegate como mostrado na sintaxe abaixo:

Sintaxe
tipo_delegate nome_variavel = delegate(lista_parametros) 
{ 
   //corpo
}
Exemplo 4
using System;
public class Program
{
    public delegate void TipoDelegate(string param);
    public delegate int TipoRetorno(int param);

	public static void Main()
	{
	    TipoDelegate Print = delegate(string param)
	    {
	         Console.WriteLine(param);
	    };
	    
	    TipoRetorno Dobro = delegate(int param)
	    {
	        return param*2;
	    };
	    
	    Print("metodo anonimo como parametro");
	    Console.WriteLine(Dobro(2));
	}
}
Saída
metodo anonimo como parametro
4

Os métodos anônimos também podem ser utilizados como parâmetro de métodos. Abaixo a sintaxe que mostra a declaração de um método que recebe um método anônimo como argumento:

Sintaxe 1
modificador_acesso delegate tipo_retorno nome_delegate(parametros);
Sintaxe 2
modificador_acesso tipo_retorno nome_metodo(tipo_delegate nome_parametro);
Sintaxe 3
nome_metodo(delegate(lista_parametros){ /*corpo */ });
Exemplo 5
using System;
public class Program
{
    //tipo delegate
    public delegate void TipoDelegate(string param);

    //método que recebe delegate
    public static void Metodo(TipoDelegate Print, string msg)// static Main
    {
        Print(msg);
    }
	public static void Main()
	{
        //método anônimo passado como argumento
        Metodo(delegate(string p)
        {  
            Console.WriteLine(p);
        }, "metodo anonimo como parametro");
	}
}
Saída
metodo anonimo como parametro

Como criamos um tipo de dado delegate, podemos também declarar tipos derivados como array de delegates. A atribuição de métodos aos elementos de um array é feita utilizando a posição/índice passado como argumento para o indexador [].

Sintaxe: Declaração
modificador_acesso tipo_delegate[] nome_array; //atributo
tipo_delegate[] nome_array; //variável
Sintaxe: Atribuição
tipo_delegate[] nome_array = { nome_metodo1, nome_metodo2, nome_metodoN };
nome_array[indice] = nome_metodo;
Sintaxe: Uso
nome_array[indice](lista_argumentos)
Exemplo 6
using System;
public class Program
{
    public delegate void TipoDelegate();

    //static Main
    public static void Metodo1(){ Console.WriteLine("Metodo1");}
    public static void Metodo2(){ Console.WriteLine("Metodo2");}
    public static void Metodo3(){ Console.WriteLine("Metodo3");}

	public static void Main()
	{
        TipoDelegate[] vetorDelegate = { Metodo1, Metodo2, Metodo3};
        vetorDelegate[0]();
        vetorDelegate[1]();
        vetorDelegate[2]();
	}
}
Saída
Metodo1
Metodo2
Metodo3
  1. 11/10/2024 - revisão 1 - Correção: Sintaxes, exemplos; Ajustes pontuais
  2. 21/03/2024 - versão inicial