Os Eventos no .NET são baseados no modelo de representante. O modelo de representante segue o padrão de design do observador, que permite a um assinante se registrar em um provedor e receber notificações dele.
Um evento é uma mensagem enviada por um objeto para sinalizar a ocorrência de uma ação ou mudança de estado, como por exemplo, se você tem uma classe que representa uma tarefa, você pode ter um evento que é disparado toda vez que uma tarefa é concluída.
Será abordado abaixo como os Eventos funcionam em código para esclarecer melhor.
Código
- Declarando um evento:
Para declarar um evento, é utilizado a palavra-chave event
, seguida por um tipo de delegate que define a assinatura dos métodos que podem responder ao evento. EventHandler<TEventArgs>
é um delegate comum usado para eventos que podem passar informações adicionais aos ouvintes.
- Classe para os argumentos do evento
Se o evento precisa passar informações extras, você cria uma classe que herda de EventArgs
. Essa classe define o que será passado como informação para aos “ouvintes” do evento.
- Notificando os assinantes do evento
Para notificar os assinantes, é definido um método protected virutal
que dispara o evento utilizando o Invoke
É utilizado o operador ?
para garantir que o evento só será invocado se houver pelo menos um assinante inscrito, para evitar exceções de referência nula. E após essa verificação o evento é chamado com this
(referência ao objeto atual) e os argumentos do evento.
- Gerando o evento
O evento pode ser gerado a partir de qualquer método da classe que queira implementá-lo, criando uma instância da classe de argumentos do evento e chamando o método que notifica os assinantes.
Nesse código é verificado se houve uma mudança de temperatura maior que >= 0.1 comparando a temperatura antiga com a atual. Assim é criado a instância da classe de argumentos do evento que recebe os parâmetros e é chamado o método que notifica os assinantes que recebe essa instancia.
- Ouvindo o evento
As classes que desejam ser “notificadas” sobre a mudança de estado da classe onde o evento é declarado, podem se inscrever para ele e definir um método que corresponda à assinatura do delegado do evento. Este método será chamado sempre que o evento for acionado.
- Testando o código
- A temperatura inicial é definido como 25 graus
- O sistema de alerta é inscrito para “ouvir” as mudanças de temperaturas
- É simulado a mudança de temperatura
- Saída
Após esse exemplo de código implementando os eventos, abaixo seram citados brevemente algumas boa práticas e considerações que são importantes saber para que tenha uma compreensão mais completa de como trabalhar com eventos em C#.
- Desinscrição de Eventos
Desinscrever-se de eventos é crucial para evitar vazamentos de memória, especialmente em cenários onde o assinante tem um ciclo de vida mais curto que o publicador. Aqui um exemplo de como se desinscrever de um evento:
2. Uso de EventHandler
vs. Delegates personalizados
EventHandler
e EventHandler<TEventArgs>
são suficientes para a maioria dos eventos. No entanto, se precisar de uma assinatura de evento que não se encaixe no padrão (object sender, TEventArgs e)
, um delegate personalizado pode ser necessário.
Exemplo com EventHandler
:
Exemplo usando um delegate personalizado:
- Thread Safety
Eventos padrão em C# não são thread-safe. Aqui está um exemplo para garantir a thread safety ao invocar um evento:
Boas práticas
- Evitar operações de longa duração nos manipuladores de eventos
Isso pode bloquear o thread que dispara o evento, causando lentidão na aplicação.
- Documentação de eventos
É importante documentar o que cada evento representa e quando é disparado, para facilitar o uso correto pelos desenvolvedores.