Lidar e elevar eventos

Os eventos em .NET são baseados no modelo de delegado. O modelo de delegado segue o padrão de design do Observador, que permite a um assinante registar-se e receber notificações de um fornecedor. Um remetente de eventos empurra uma notificação de que um evento aconteceu, e um recetor de eventos recebe essa notificação e define uma resposta ao mesmo. Este artigo descreve os principais componentes do modelo delegado, como consumir eventos em aplicações e como implementar eventos no seu código.

evento

Um evento é uma mensagem enviada por um objeto para sinalizar a ocorrência de uma ação. A ação pode ser causada pela interação do utilizador, como um clique de botão, ou pode resultar de outra lógica de programa, como alterar o valor de uma propriedade. O objeto que levanta o evento é chamado de remetente do evento. O remetente do evento não sabe qual o objeto ou método que receberá (manusear) os eventos que ele levanta. O evento é tipicamente 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, utilize o C# event ou a palavra-chave Visual Basic Event na assinatura da sua classe de eventos e especifique o tipo de delegado para o evento. Os delegados são descritos na secção seguinte.

Normalmente, para criar um evento, adiciona-se um método marcado como protected e virtual (em C#) ou ProtectedOverridable (em Visual Basic). Nomeie este método OnEventName; por exemplo, OnDataReceived. O método deve tomar um parâmetro que especifique um objeto de dados do evento, que é um objeto do tipo EventArgs ou um tipo derivado. Você fornece este método para permitir que as classes derivadas sobreponha a lógica para elevar o evento. Uma classe derivada deve sempre ligar para o On método EventName da classe base para garantir que os delegados registados recebam o evento.

O exemplo a seguir mostra como declarar um evento chamado ThresholdReached. O evento está associado ao EventHandler delegado e criado num método denominado OnThresholdReached.

class Counter
{
    public event EventHandler ThresholdReached;

    protected virtual void OnThresholdReached(EventArgs e)
    {
        EventHandler handler = ThresholdReached;
        handler?.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

Delegados

Um delegado é um tipo que detém uma referência a um método. Um delegado é declarado com uma assinatura que mostra o tipo de devolução e os parâmetros para os métodos que refere, e pode conter referências apenas a métodos que correspondam à sua assinatura. Um delegado é, portanto, equivalente a um ponteiro de função tipo seguro ou a uma chamada. Uma declaração de delegado é suficiente para definir uma classe de delegado.

Os delegados têm muitas utilizações em .NET. No contexto dos acontecimentos, um delegado é um intermediário (ou mecanismo semelhante a um ponteiro) entre a fonte do evento e o código que trata do evento. Associa um delegado a um evento, incluindo o tipo de delegado na declaração do evento, como mostra o exemplo na secção anterior. Para mais informações sobre os delegados, consulte a Delegate turma.

.NET fornece os EventHandler e EventHandler<TEventArgs> delegados para apoiar a maioria dos cenários do evento. Utilize o EventHandler delegado para todos os eventos que não incluam dados do evento. Utilize o EventHandler<TEventArgs> delegado para eventos que incluam dados sobre o evento. Estes delegados não têm valor de tipo de retorno e tomam dois parâmetros (um objeto para a origem do evento, e um objeto para dados do evento).

Os delegados são multicast, o que significa que podem realizar referências a mais de um método de tratamento de eventos. Para mais detalhes, consulte a Delegate página de referência. Os delegados proporcionam flexibilidade e controlo fino no manuseamento de eventos. Um delegado atua como um despachante de eventos para a classe que eleva o evento mantendo uma lista de manipuladores de eventos registados para o evento.

Para cenários em que os EventHandler delegados e EventHandler<TEventArgs> delegados não funcionam, pode definir um delegado. Cenários que exigem que você defina um delegado são muito raros, como quando você deve trabalhar com código que não reconhece genéricos. Marque um delegado com a palavra-chave C# delegate e Visual Basic Delegate na declaração. O exemplo a seguir mostra como declarar um delegado nomeado ThresholdReachedEventHandler.

public delegate void ThresholdReachedEventHandler(object sender, ThresholdReachedEventArgs e);
Public Delegate Sub ThresholdReachedEventHandler(sender As Object, e As ThresholdReachedEventArgs)

Dados do evento

Os dados associados a um evento podem ser fornecidos através de uma classe de dados de eventos. .NET fornece muitas classes de dados de eventos que pode usar nas suas aplicações. Por exemplo, a SerialDataReceivedEventArgs classe é a classe de dados do evento para o SerialPort.DataReceived evento. .NET segue um padrão de nomeação de terminar todas as classes de dados de eventos com EventArgs. Você determina qual a classe de dados do evento associada a um evento olhando para o delegado para o evento. Por exemplo, o SerialDataReceivedEventHandler delegado inclui a SerialDataReceivedEventArgs classe como um dos seus parâmetros.

A EventArgs classe é o tipo base para todas as classes de dados do evento. EventArgs é também a classe que usa quando um evento não tem quaisquer dados associados a ele. Quando cria um evento que se destina apenas a notificar outras classes de que algo aconteceu e não precisa de passar quaisquer dados, inclua a EventArgs classe como o segundo parâmetro no delegado. Pode passar o EventArgs.Empty valor quando não são fornecidos dados. O EventHandler delegado inclui a EventArgs classe como parâmetro.

Quando pretender criar uma aula de dados de eventos personalizada, crie uma classe que deriva de , e, em EventArgsseguida, forneça todos os membros necessários para passar dados que estão relacionados com o evento. Normalmente, deve usar o mesmo padrão de nomeação que .NET e terminar o nome da classe de dados do evento com EventArgs.

O exemplo a seguir mostra uma classe de dados de eventos chamada ThresholdReachedEventArgs. Contém propriedades específicas para o evento ser levantado.

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

Processadores de eventos

Para responder a um evento, você define um método de manipulador de eventos no recetor do evento. Este método deve coincidir com a assinatura do delegado para o evento que está a lidar. No manipulador de eventos, executa as ações que são necessárias quando o evento é levantado, como recolher a entrada do utilizador depois de o utilizador clicar num botão. Para receber notificações quando o evento ocorrer, o seu método de manipulador de eventos deve subscrever o evento.

O exemplo a seguir mostra um método de manipulador de eventos nomeado c_ThresholdReached que corresponde à assinatura do EventHandler delegado. O método subscreve o ThresholdReached evento.

class Program
{
    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

Manipuladores de eventos estáticos e dinâmicos

.NET permite que os assinantes se registem para notificações de eventos, quer estáticas quer dinamicamente. Os manipuladores de eventos estáticos estão em vigor para toda a vida da classe cujos eventos eles lidam. Os manipuladores dinâmicos de eventos são explicitamente ativados e desativados durante a execução do programa, geralmente em resposta a alguma lógica de programa condicional. Por exemplo, podem ser utilizados se as notificações de eventos forem necessárias apenas em determinadas condições ou se uma aplicação fornecer vários manipuladores de eventos e as condições de tempo de execução definirem o adequado para usar. O exemplo na secção anterior mostra como adicionar dinamicamente um manipulador de eventos. Para mais informações, consulte Eventos (em Visual Basic) e Eventos (em C#).

Elevar vários eventos

Se a sua classe levantar vários eventos, o compilador gera 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 pode não ser aceitável. Para estas situações, a .NET fornece propriedades de eventos que pode utilizar com outra estrutura de dados à sua escolha para armazenar delegados de eventos.

As propriedades do evento consistem em declarações de eventos acompanhadas de acessórios de eventos. Os acessórios do evento são métodos que define para adicionar ou remover instâncias de delegados de eventos da estrutura de dados de armazenamento. Note que as propriedades do evento são mais lentas do que os campos de eventos, porque cada delegado de evento deve ser recuperado antes de poder ser invocado. A troca é entre a memória e a velocidade. Se a sua classe define muitos eventos que são pouco frequentemente elevados, você vai querer implementar propriedades de eventos. Para obter mais informações, consulte Como: Lidar com vários eventos utilizando propriedades de eventos.

Título Descrição
Como: Aumentar e Consumir Eventos Contém exemplos de elevação e consumo de eventos.
Como: Lidar com vários eventos usando propriedades de eventos Mostra como usar propriedades de eventos para lidar com vários eventos.
Padrão de design do observador Descreve o padrão de design que permite a um assinante registar-se e receber notificações de um fornecedor.

Ver também