Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Os eventos no .NET são baseados no modelo delegado. O modelo delegado segue o padrão de design do observador, que permite que um assinante se registre e receba notificações de um provedor. Um remetente de eventos envia uma notificação por push quando ocorre um evento. Um receptor de evento define a resposta. Este artigo descreve os principais componentes do modelo delegado, como consumir eventos em aplicativos e como implementar eventos em seu código.
Gerar eventos com um remetente de eventos
Um evento é uma mensagem enviada por um objeto para sinalizar a ocorrência de uma ação. A ação pode ser uma interação com o usuário, como o pressionamento de um botão, ou pode resultar de outra lógica de programa, como uma alteração de valor de propriedade. O objeto que aciona o evento é chamado de remetente do evento. O remetente de eventos não conhece o objeto ou o método que recebe (manipula) os eventos gerados. O evento geralmente é um membro do remetente do evento. Por exemplo, o Click evento é um membro da Button classe e o PropertyChanged evento é um membro da classe que implementa a INotifyPropertyChanged interface.
Para definir um evento, use o evento C# ou a palavra-chave Evento do Visual Basic na assinatura da classe de evento e especifique o tipo de delegado para o evento. Os delegados são descritos na próxima seção.
Normalmente, para gerar um evento, você adiciona um método marcado como protected e virtual (em C#) ou Protected ( Overridable no Visual Basic). A convenção de nomenclatura para o método é On<EventName>, como OnDataReceived. O método deve usar um parâmetro que especifica um objeto de dados de evento, que é um objeto de tipo EventArgs ou um tipo derivado. Você fornece esse método para permitir que classes derivadas substituam a lógica para gerar o evento. Uma classe derivada sempre deve chamar o On<EventName> método da classe base para garantir que os delegados registrados recebam o evento.
O exemplo a seguir mostra como declarar um evento chamado ThresholdReached. O evento está associado ao representante EventHandler e é gerado em um método chamado OnThresholdReached:
class Counter
{
public event EventHandler ThresholdReached;
protected virtual void OnThresholdReached(EventArgs e)
{
ThresholdReached?.Invoke(this, e);
}
// provide remaining implementation for the class
}
Public Class Counter
Public Event ThresholdReached As EventHandler
Protected Overridable Sub OnThresholdReached(e As EventArgs)
RaiseEvent ThresholdReached(Me, e)
End Sub
' provide remaining implementation for the class
End Class
Declarar assinaturas de delegados para manipuladores de eventos
Um representante é um tipo que contém uma referência a um método. Um delegado é declarado com uma assinatura que indica o tipo de retorno e os parâmetros dos métodos que ele referencia. Ele pode conter referências somente a métodos que correspondem à sua assinatura. Um delegado é equivalente a um ponteiro de função de tipo seguro ou a um retorno de chamada. Uma declaração de delegado é suficiente para definir uma classe delegada.
Os delegados têm muitos usos no .NET. No contexto de eventos, um delegado é um intermediário (ou mecanismo de ponteiro) entre a origem do evento e o código que manipula o evento. Você associa um delegado a um evento, incluindo o tipo delegado na declaração de evento, conforme mostrado no exemplo na seção anterior. Para obter mais informações sobre delegados, consulte a Delegate classe.
O .NET fornece os delegados EventHandler e EventHandler<TEventArgs> para dar suporte à maioria dos cenários de eventos. Use o representante EventHandler para todos os eventos que não incluem dados de evento. Use o representante EventHandler<TEventArgs> para eventos que incluem dados sobre o evento. Esses representantes não têm valor de tipo de retorno e usam dois parâmetros (um objeto para a origem do evento e um objeto para dados do evento).
Os delegados são objetos de classe multicast , o que significa que eles podem manter referências a mais de um método de manipulação de eventos. Para obter mais informações, consulte a Delegate página de referência. Os delegados fornecem flexibilidade e controle refinado na manipulação de eventos. Um representante atua como um dispatcher de evento para a classe que aciona o evento ao manter uma lista de manipuladores de eventos registrados para o evento.
Use os tipos de EventHandler e EventHandler<TEventArgs> delegados para definir o delegado necessário. Você marca um delegado de delegate tipo em C# ou de Delegate tipo em Visual Basic na declaração. O exemplo a seguir mostra como declarar um delegado chamado ThresholdReachedEventHandler:
public delegate void ThresholdReachedEventHandler(object sender, ThresholdReachedEventArgs e);
Public Delegate Sub ThresholdReachedEventHandler(sender As Object, e As ThresholdReachedEventArgs)
Trabalhar com classes de dados de eventos
Os dados associados a um evento podem ser fornecidos por meio de uma classe de dados de evento. O .NET fornece muitas classes de dados de eventos que você pode usar em seus aplicativos. Por exemplo, a classe SerialDataReceivedEventArgs é a classe de dados do evento SerialPort.DataReceived. O .NET segue um padrão de nomenclatura em que todas as classes de dados de evento terminam com o EventArgs sufixo. Você determina qual classe de dados de evento está associada a um evento examinando o delegado do evento. Por exemplo, o SerialDataReceivedEventHandler delegado inclui a SerialDataReceivedEventArgs classe como um parâmetro.
A EventArgs classe normalmente é o tipo base para classes de dados de eventos. Você também usará essa classe se um evento não tiver nenhum dado associado a ele. Quando você cria um evento que notifica os assinantes de que algo aconteceu sem nenhum dado adicional, inclua a EventArgs classe como o segundo parâmetro no delegado. Você pode passar o EventArgs.Empty valor quando nenhum dado é fornecido. O EventHandler delegado inclui a EventArgs classe como um parâmetro.
Você pode criar uma classe que deriva da classe EventArgs para fornecer todos os membros necessários para passar dados relacionados ao evento. Normalmente, você deve usar o mesmo padrão de nomenclatura que o .NET e encerrar o nome da classe de dados de evento com o EventArgs sufixo.
O exemplo a seguir mostra uma classe de dados de evento nomeada ThresholdReachedEventArgs que contém propriedades específicas para o evento que está sendo gerado:
public class ThresholdReachedEventArgs : EventArgs
{
public int Threshold { get; set; }
public DateTime TimeReached { get; set; }
}
Public Class ThresholdReachedEventArgs
Inherits EventArgs
Public Property Threshold As Integer
Public Property TimeReached As DateTime
End Class
Responder a eventos com manipuladores
Para responder a um evento, defina um método de manipulador de eventos no receptor de eventos. Esse método deve corresponder à assinatura do representante para o evento que está sendo manipulado. No manipulador de eventos, você executa as ações que são necessárias quando o evento é acionado, como coletar a entrada do usuário depois que o usuário pressiona um botão. Para receber notificações quando o evento ocorrer, o método do manipulador de eventos deve assinar o evento.
O exemplo a seguir mostra um método de manipulador de eventos chamado c_ThresholdReached que corresponde à assinatura do EventHandler delegado. O método está inscrito no evento ThresholdReached:
class ProgramTwo
{
static void Main()
{
var c = new Counter();
c.ThresholdReached += c_ThresholdReached;
// provide remaining implementation for the class
}
static void c_ThresholdReached(object sender, EventArgs e)
{
Console.WriteLine("The threshold was reached.");
}
}
Module Module1
Sub Main()
Dim c As New Counter()
AddHandler c.ThresholdReached, AddressOf c_ThresholdReached
' provide remaining implementation for the class
End Sub
Sub c_ThresholdReached(sender As Object, e As EventArgs)
Console.WriteLine("The threshold was reached.")
End Sub
End Module
Usar manipuladores de eventos estáticos e dinâmicos
O .NET permite que os assinantes se registrem para notificações de evento estaticamente ou dinamicamente. Os manipuladores de eventos estáticos permanecem em vigor por toda a vida da classe cujos eventos eles manipulam. Manipuladores de eventos dinâmicos são ativados e desativados explicitamente durante a execução do programa, geralmente em resposta a alguma lógica de programa condicional. Você pode usar manipuladores dinâmicos quando as notificações de evento são necessárias somente em determinadas condições ou quando as condições de runtime determinam o manipulador específico a ser chamado. O exemplo na seção anterior mostra como adicionar dinamicamente um manipulador de eventos. Para obter mais informações, consulte Eventos (no Visual Basic) e Eventos (em C#).
Gerar vários eventos
Se a classe gerar vários eventos, o compilador gerará um campo por instância de delegado de evento. Se o número de eventos for grande, o custo de armazenamento de um campo por delegado poderá não ser aceitável. Para esses cenários, o .NET fornece propriedades de evento que você pode usar com outra estrutura de dados de sua escolha para armazenar delegados de eventos.
As propriedades de evento consistem em declarações de evento acompanhadas por acessadores de evento. Os acessadores de eventos são métodos que você define para adicionar ou remover instâncias de delegado de eventos da estrutura de dados de armazenamento.
Observação
As propriedades de evento são mais lentas que os campos de evento, pois cada representante de evento deve ser recuperado para que possa ser invocado.
A troca é entre memória e velocidade. Se sua classe definir muitos eventos que são raramente acionados, você deverá implementar propriedades de eventos. Para obter mais informações, consulte Manipular vários eventos usando propriedades de evento.
Explorar tarefas relacionadas
Os recursos a seguir descrevem outras tarefas e conceitos relacionados ao trabalho com eventos:
- Gerar e consumir eventos: encontre exemplos de como gerar e consumir eventos.
- Manipular vários eventos com propriedades de evento: descubra como usar as propriedades do evento para lidar com vários eventos.
- Explore o padrão de design do observador: examine um padrão de design que permite que um assinante se registre e receba notificações de um provedor.
Examinar a referência de especificação
A documentação de referência de especificação está disponível para as APIs que dão suporte ao tratamento de eventos:
| Nome da API | Tipo de API | Referência |
|---|---|---|
| EventHandler | Delegado | EventHandler |
| ManipuladorDeEvento<TEventArgs> | Delegado | EventHandler<TEventArgs> |
| EventArgs | Classe | EventArgs |
| Delegado | Classe | Delegate |