Menu
Coddy logo textTech

Delegates e Eventos

Parte da seção Programação Orientada a Objetos do Journey de C# da Coddy — lição 43 de 70.

Um delegate é um tipo que representa uma referência a um método. Pense nele como uma variável que contém um método em vez de dados. Isso permite que você passe métodos como argumentos, armazene-os em coleções e os chame dinamicamente.

Você declara um delegate especificando a assinatura do método que ele pode referenciar:

public delegate void Notify(string message);

public class Publisher
{
    public void SendAlert(string msg) => Console.WriteLine("Alert: " + msg);
}

// Uso
Notify notifier = new Publisher().SendAlert;
notifier("System started");  // Alert: System started

Eventos baseiam-se em delegates para implementar o padrão publish-subscribe. Uma classe dispara um evento, e outras classes podem se inscrever para receber notificações. A palavra-chave event restringe como o delegate pode ser usado - assinantes podem apenas adicionar ou remover manipuladores, não invocar o evento diretamente.

public class Button
{
    public event Action Clicked;
    
    public void Click()
    {
        Clicked?.Invoke();  // Notifica todos os assinantes
    }
}

// Inscrevendo-se
Button btn = new Button();
btn.Clicked += () => Console.WriteLine("Button was clicked!");
btn.Click();  // O botão foi clicado!

O operador += inscreve um manipulador, enquanto o -= cancela a inscrição. O padrão ?.Invoke() chama o evento com segurança apenas se houver assinantes. Eventos são fundamentais para aplicações GUI, motores de jogos e qualquer sistema onde objetos precisam reagir a mudanças sem acoplamento rígido.

challenge icon

Desafio

Fácil

Vamos construir um sistema de monitoramento de temperatura que utiliza delegates e eventos para notificar os assinantes sempre que a temperatura mudar. Este é um exemplo clássico do padrão publish-subscribe que os eventos permitem de forma tão elegante.

Você organizará seu código em dois arquivos:

  • TemperatureMonitor.cs: Crie uma classe TemperatureMonitor no namespace Monitoring que atua como o publicador. Seu monitor deve:
    • Ter um campo privado para armazenar a temperatura atual
    • Declarar um evento usando Action<int> chamado TemperatureChanged que é disparado sempre que a temperatura é atualizada
    • Ter uma propriedade Temperature (int) onde o setter atualiza o campo privado e dispara o evento com o novo valor da temperatura
    Lembre-se de usar o padrão ?.Invoke() para disparar o evento com segurança apenas quando houver assinantes.
  • Program.cs: No seu arquivo principal, crie um TemperatureMonitor e assine dois manipuladores diferentes para o seu evento TemperatureChanged:
    • Um manipulador que imprime: Alert: Temperature is now {value} degrees
    • Outro manipulador que imprime: Logged: {value}
    Após assinar ambos os manipuladores, defina a temperatura duas vezes usando os valores da entrada. Cada vez que você definir a temperatura, ambos os manipuladores devem responder.

Você receberá duas entradas:

  • Primeiro valor de temperatura (inteiro)
  • Segundo valor de temperatura (inteiro)

Por exemplo, se as entradas forem 25 e 30, a saída deve ser:

Alert: Temperature is now 25 degrees
Logged: 25
Alert: Temperature is now 30 degrees
Logged: 30

Observe como a definição da propriedade Temperature notifica automaticamente todos os assinantes - o monitor não precisa saber nada sobre quem está ouvindo. Essa é a beleza da abordagem orientada a eventos!

Folha de consulta

Um delegate é um tipo que representa uma referência a um método, permitindo que você passe métodos como argumentos, armazene-os em coleções e os chame dinamicamente.

Declare um delegate especificando a assinatura do método:

public delegate void Notify(string message);

public class Publisher
{
    public void SendAlert(string msg) => Console.WriteLine("Alert: " + msg);
}

// Usage
Notify notifier = new Publisher().SendAlert;
notifier("System started");  // Alert: System started

Eventos implementam o padrão publish-subscribe (publicador-assinante) usando delegates. A palavra-chave event restringe o uso do delegate - os assinantes podem apenas adicionar ou remover manipuladores, não invocar o evento diretamente.

public class Button
{
    public event Action Clicked;
    
    public void Click()
    {
        Clicked?.Invoke();  // Notify all subscribers
    }
}

// Subscribing
Button btn = new Button();
btn.Clicked += () => Console.WriteLine("Button was clicked!");
btn.Click();  // Button was clicked!

Use += para assinar um manipulador e -= para cancelar a assinatura. O padrão ?.Invoke() chama o evento com segurança apenas se houver assinantes.

Experimente você mesmo

using System;
using Monitoring;

class Program
{
    public static void Main(string[] args)
    {
        // Ler entrada
        int temp1 = Convert.ToInt32(Console.ReadLine());
        int temp2 = Convert.ToInt32(Console.ReadLine());

        // TODO: Criar uma instância de TemperatureMonitor

        // TODO: Inscrever um manipulador que imprime: "Alert: Temperature is now {value} degrees"

        // TODO: Inscrever outro manipulador que imprime: "Logged: {value}"

        // TODO: Definir a temperatura para temp1

        // TODO: Definir a temperatura para temp2
    }
}
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos