Médio C#

Evento com múltiplos assinantes

Enunciado

Crie uma classe Termometro que possui um evento TemperaturaMudou do tipo Action<double>. A classe deve ter um método AlterarTemperatura(double novaTemp) que dispara o evento. No Main, inscreva dois assinantes: um que imprime a temperatura em Celsius e outro que converte para Fahrenheit. Altere a temperatura e exiba as mensagens.

Requisitos

  • Declare o evento TemperaturaMudou usando Action<double>.
  • Implemente AlterarTemperatura que atualiza a temperatura e dispara o evento com ?.Invoke.
  • No Main, inscreva dois métodos (ou lambdas) no evento e chame AlterarTemperatura uma vez.
  • Exiba a temperatura em Celsius e Fahrenheit.

Código inicial

using System;

public class Termometro
{
    // TODO: declare o evento

    public void AlterarTemperatura(double novaTemp)
    {
        // TODO: atualize e dispare o evento
    }
}

public class Programa
{
    public static void Main()
    {
        // TODO: inscreva assinantes e altere a temperatura
    }
}

Saída esperada

Temperatura: 25°C
Temperatura: 77°F
Ver dica

Use public event Action<double>? TemperaturaMudou; e dentro do método chame TemperaturaMudou?.Invoke(novaTemp);. Para converter para Fahrenheit: F = C * 9 / 5 + 32.

Mostrar solução
using System;

public class Termometro
{
    // Evento que notifica mudanças de temperatura
    public event Action<double>? TemperaturaMudou;

    public void AlterarTemperatura(double novaTemp)
    {
        // Dispara o evento de forma segura
        TemperaturaMudou?.Invoke(novaTemp);
    }
}

public class Programa
{
    public static void Main()
    {
        var termometro = new Termometro();

        // Assinante 1: exibe em Celsius
        termometro.TemperaturaMudou += temp =>
            Console.WriteLine($"Temperatura: {temp}°C");

        // Assinante 2: converte para Fahrenheit
        termometro.TemperaturaMudou += temp =>
            Console.WriteLine($"Temperatura: {temp * 9 / 5 + 32}°F");

        // Altera a temperatura, disparando o evento para os dois assinantes
        termometro.AlterarTemperatura(25);
    }
}

Passo a passo

  1. Declaramos o evento TemperaturaMudou como Action<double>?. O ? indica que o evento pode ser nulo se ninguém se inscreveu.
  2. O método AlterarTemperatura recebe a nova temperatura e chama TemperaturaMudou?.Invoke(novaTemp). O operador ?. evita NullReferenceException.
  3. No Main, criamos uma instância de Termometro.
  4. Inscrevemos o primeiro assinante com += e uma lambda que imprime em Celsius.
  5. Inscrevemos o segundo assinante com += e uma lambda que converte para Fahrenheit e imprime.
  6. Chamamos AlterarTemperatura(25), que dispara o evento. Como é multicast, as duas lambdas são executadas na ordem de inscrição.

Por que funciona

O evento encapsula um delegate multicast. A palavra-chave event impede que código externo dispare o evento ou atribua um novo delegate diretamente (só permite += e -=). Isso garante que apenas a classe Termometro controle quando notificar. O Action<double> é um delegate genérico que representa um método que recebe um double e não retorna valor. A chamada ?.Invoke percorre a lista de inscritos e chama cada um.

Erros comuns

  • Esquecer o ? no evento: public event Action<double> TemperaturaMudou; gera aviso de possível nulo. Use ? e ?.Invoke.
  • Tentar disparar o evento fora da classe: termometro.TemperaturaMudou(25); não compila porque eventos só podem ser disparados dentro da classe que os declara.
  • Atribuir com = em vez de +=: termometro.TemperaturaMudou = ... não compila para eventos (a não ser dentro da classe). Use += para inscrever.
  • Não tratar múltiplos assinantes: se um assinante lançar exceção, os seguintes não são chamados. Considere isolar chamadas se necessário.

Outra forma de resolver

Usar um delegate personalizado em vez de Action<double>:

public delegate void TemperaturaHandler(double temp);
public event TemperaturaHandler? TemperaturaMudou;

A escolha é estilística; Action<double> é mais conciso.

Saída esperada

Temperatura: 25°C
Temperatura: 77°F