English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Tutorial Básico de C#

Tutorial Avançado de C#

C# Orientado a Objetos (OOP)

Delegado (Delegate) do C#

E se quisermos passar uma função como parâmetro? Como o C# lida com funções de callback ou manipuladores de eventos? A resposta é-delegado (delegate). O delegado (Delegate) é uma variável de tipo de referência que contém uma referência a um método. A referência pode ser alterada em tempo de execução.

O delegado éDefinir a assinatura do métododo tipo de dados de referência. Você pode definir uma variável de delegado, como outros tipos de dados, que pode referenciar qualquer método que tenha a mesma assinatura que o delegado.

Trabalhar com delegados envolve três passos:

  1. Declaração de Delegação

  2. Definir o método de destino

  3. Chamar o delegado

Pode-se declarar um delegado usando a palavra-chave delegate e a assinatura da função, conforme mostrado a seguir.

  Sintaxe do delegado

[modificador de acesso] delegate [tipo de retorno] [nome do delegado]([parâmetros])

A seguir, declara-se um delegado chamado MyDelegate.

public delegate void MyDelegate(string msg);

Acima, declaramos um MyDelegate comvoidTipo de retorno e parâmetro de string. O delegado pode ser declarado fora ou dentro da classe. De fato, deve ser declarado fora da classe.

Após declarar o delegado, precisamos definir o método de destino ou expressão lambda. Podemos criar um objeto do delegado usando a palavra-chave new e passar um método cujo sinal compatível com o delegado.

public delegate void MyDelegate(string msg); // Declaração de Delegação
//Definir o método de destino
MyDelegate del = new MyDelegate(MethodA);
// ou
MyDelegate del = MethodA; 
// ou expressão lambda 
MyDelegate del = (string msg) => Console.WriteLine(msg);
// Método de destino
static void MethodA(string message)
{
    Console.WriteLine(message);
}

Você pode definir o método de destino diretamente, sem criar um objeto de delegado, por exemplo, MyDelegate del = MethodA.

Após definir o método de destino, você pode usar o método Invoke() ou o operador () para chamar o delegado.

del.Invoke("Hello World!");
//ou 
del("Hello World!");

A seguir está um exemplo completo de delegado.

public delegate void MyDelegate(string msg); //Declaração de Delegação
class Program
{
    static void Main(string[] args)
    {
        MyDelegate del = ClassA.MethodA;
        del("Hello World");
        del = ClassB.MethodB;
        del("Hello World");
        del = (string msg) => Console.WriteLine("Chamado expressão lambda: ") + msg);
        del("Hello World");
    }
}
class ClassA
{
    static void MethodA(string message)
    {
        Console.WriteLine("Chamado ClassA.MethodA() com parâmetro: ") + message);
    }
}
class ClassB
{
    static void MethodB(string message)
    {
        Console.WriteLine("Chamado ClassB.MethodB() com parâmetro: ") + message);
    }
}

A figura a seguir ilustra o delegado.

Delegado C#

Passar o delegado como parâmetro

Os métodos podem ter parâmetros do tipo delegado, conforme mostrado a seguir.

public delegate void MyDelegate(string msg); //Declaração de Delegação
class Program
{
    static void Main(string[] args)
    {
        MyDelegate del = ClassA.MethodA;
        InvokeDelegate(del);
        del = ClassB.MethodB;
        InvokeDelegate(del);
        del = (string msg) => Console.WriteLine("Chamado expressão lambda: ") + msg);
        InvokeDelegate(del);
    }
    static void InvokeDelegate(MyDelegate del) // Parâmetros do tipo MyDelegate
    {
        del("Hello World");
    }
}
class ClassA
{
    static void MethodA(string message)
    {
        Console.WriteLine("Chamado ClassA.MethodA() com parâmetro: ") + message);
    }
}
class ClassB
{
    static void MethodB(string message)
    {
        Console.WriteLine("Chamado ClassB.MethodB() com parâmetro: ") + message);
    }
}

No .NET, os tipos Func e Action são delegados genéricos integrados, que devem ser usados para os delegados mais comuns, em vez de criar novos delegados personalizados.

Delegado de multicast

Um delegado pode apontar para vários métodos. Um delegado que aponta para vários métodos é chamado de delegado de multicast.+” ou “+O operador de atribuição (=) adiciona a função à lista de chamadas, enquanto o-" e "-O operador de atribuição (=) remove-o.

public delegate void MyDelegate(string msg); //Declarar um delegado
class Program
{
    static void Main(string[] args)
    {
        MyDelegate del1 = ClassA.MethodA;
        MyDelegate del2 = ClassB.MethodB;
        MyDelegate del = del1 + del2; // del1 + del2
        del("Hello World");
        MyDelegate del3 = (string msg) => Console.WriteLine("Chamado expressão lambda: ") + msg);
        del += del3; // del1 + del2 + del3
        del("Hello World");
        del = del - del2; // Remover del2
        del("Hello World");
        del -= del1 // Remover del1
        del("Hello World");
    }
}
class ClassA
{
    static void MethodA(string message)
    {
        Console.WriteLine("Chamado ClassA.MethodA() com parâmetro: ") + message);
    }
}
class ClassB
{
    static void MethodB(string message)
    {
        Console.WriteLine("Chamado ClassB.MethodB() com parâmetro: ") + message);
    }
}

Os operadores de adição e subtração sempre funcionam como parte de uma atribuição: del1+=del2; com del1=del1+del2Idêntico; a subtração também é assim.

Se o delegado retornar um valor, então, ao chamar o delegado de multicast, o valor do método de destino atribuído por último será retornado.

public delegate int MyDelegate(); //Declaração de Delegação
class Program
{
    static void Main(string[] args)
    {
        MyDelegate del1 = ClassA.MethodA;
        MyDelegate del2 = ClassB.MethodB;
        MyDelegate del = del1 + del2; 
        Console.WriteLine(del());// Retorno200
    }
}
class ClassA
{
    static int MethodA()
    {
        return 100;
    }
}
class ClassB
{
    static int MethodB()
    {
        return 200;
    }
}

Delegados Genéricos

Pode-se definir delegações genéricas da mesma forma que delegações, mas pode-se usar parâmetros de tipo genérico ou tipo de retorno. Ao configurar o método de destino, é necessário especificar o tipo genérico.

Por exemplo, veja a delegação genérica usada para os parâmetros int e string a seguir.

public delegate T add<T>(T param1, T param2; // Delegados Genéricos
class Program
{
    static void Main(string[] args)
    {
        add<int> sum = Sum;
        Console.WriteLine(sum(10, 20));
        add<string> con = Concat;
        Console.WriteLine(conct("Hello ", "World!!"));
    }
    public static int Sum(int val1, int val2)
    {
        return val1 + val2;
    }
    public static string Concat(string str1, string str2)
    {
        return str1 + str2;
    }
}

Delegação também é usada para declarar eventos e métodos anônimos.

 Ponto a lembrar

  1. Delegação é um tipo de dados de referência de tipo de dados que define a assinatura.

  2. Variáveis de tipo de delegação podem referenciar qualquer método que tenha a mesma assinatura que a delegação.

  3. Sintaxe:[Acessador de Acesso] Delegado [Tipo de Retorno] [Nome do Delegado]([Parâmetros])([access modifier] delegate [return type] [delegate name]([parameters]))

  4. A assinatura do método de destino deve coincidir com a assinatura do delegado.

  5. O delegado pode ser chamado como uma função comum ou método invoke().

  6. Você pode usar “ +” ou “ + O operador de atribuição (=) atribui vários métodos ao delegado e usa “-” ou “-O operador de atribuição (=) remove-o. Ele é chamado de delegado de multicast.

  7. Se o delegado de multicast retornar um valor, ele retornará o valor do último método de destino atribuído.

  8. O delegado é usado para declarar eventos e métodos anônimos no C#.