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
TemperaturaMudouusandoAction<double>. - Implemente
AlterarTemperaturaque atualiza a temperatura e dispara o evento com?.Invoke. - No
Main, inscreva dois métodos (ou lambdas) no evento e chameAlterarTemperaturauma 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
- Declaramos o evento
TemperaturaMudoucomoAction<double>?. O?indica que o evento pode ser nulo se ninguém se inscreveu. - O método
AlterarTemperaturarecebe a nova temperatura e chamaTemperaturaMudou?.Invoke(novaTemp). O operador?.evitaNullReferenceException. - No
Main, criamos uma instância deTermometro. - Inscrevemos o primeiro assinante com
+=e uma lambda que imprime em Celsius. - Inscrevemos o segundo assinante com
+=e uma lambda que converte para Fahrenheit e imprime. - 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