Entendendo os eventos em C#
Em C#, eventos são um conceito fundamental que muitos desenvolvedores utilizam, mas que podem não compreender completamente, principalmente quando se trata de criar seus próprios eventos. Tim Corey oferece um guia completo sobre como criar e usar eventos, explorando as melhores práticas e recursos avançados em seu vídeo " C# Events - Creating and Consuming Events in Your Application ".
Neste artigo, vamos explorar os eventos em C#, com foco em sua sintaxe, como são definidos e como ajudam a resolver problemas comuns de programação, usando exemplos em vídeo de Tim Corey. Compreender o tratamento de eventos em C# é essencial para criar aplicações responsivas, e este artigo ajudará você a entender os conceitos fundamentais de registro de erros personalizado, tratamento de exceções e programação orientada a eventos.
Introdução aos Eventos
Em C# e em outras linguagens de programação, os eventos desempenham um papel fundamental na programação orientada a eventos, permitindo que os aplicativos respondam a ações como interações do usuário ou alterações do sistema. Em comparação com outras linguagens de programação, o C# oferece uma abordagem estruturada para lidar com eventos, tornando-o ideal tanto para aplicações rápidas quanto para aplicações pequenas. Em C#, os eventos são acionados por ações específicas, e essas ações invocam os manipuladores de eventos correspondentes para executar as tarefas desejadas.
Tim começa explicando que a maioria dos desenvolvedores está familiarizada com eventos em C#, mas pode não saber como criar eventos personalizados. O objetivo do vídeo é apresentar os eventos, demonstrar como criar eventos personalizados, discutir suas funcionalidades e descrever as melhores práticas.
Demonstração do Aplicativo - Passo a Passo
Tim usa um aplicativo bancário simples, desenvolvido com Windows Forms (WinForms), para demonstrar os eventos. O aplicativo simula operações bancárias básicas para um cliente, incluindo a visualização de saldos e o registro de transações.
-
Visão geral do aplicativo :
- O aplicativo possui dois formulários: um para exibir saldos e transações da conta e outro para registrar novas transações.
- Inclui botões para simular compras com cartão de crédito e lidar com descobertos, transferindo fundos da poupança para a conta corrente.
-
Formulário principal :
- Exibe o nome do cliente e os saldos de suas contas corrente e poupança.
- Exibe a lista de transações de ambas as contas.
- Contém um botão para abrir o formulário de registro de transações.
-
Formulário de Transação :
- Permite ao usuário inserir valores de transação.
- Simula a realização de compras e lida com descobertos bancários transferindo fundos da poupança para a conta corrente.
Código por trás do aplicativo de demonstração
Tim explica o código de backend do aplicativo bancário de demonstração:
-
Classe de Cliente :
- Representa um cliente com propriedades referentes ao nome do cliente e duas contas (corrente e poupança). A classe Cliente é simples, mas serve como um bom ponto de partida para entender como gerenciar várias contas.
-
Classe da conta :
- Gerencia os detalhes de uma conta bancária, incluindo o nome da conta, o saldo e a lista de transações.
- A propriedade Saldo é do tipo decimal para cálculos monetários precisos.
- A propriedade Transactions é uma lista somente leitura para impedir modificações externas.
-
Gerenciamento de depósitos e pagamentos :
- Método AddDeposit : Adiciona um depósito à conta, atualiza o saldo e registra a transação.
- Método de pagamento MakePayment : Gerencia saques, incluindo a verificação de fundos suficientes e o gerenciamento da proteção contra sobregiro, transferindo fundos de uma conta reserva, se necessário.
-
Proteção contra sobregiro :
- O aplicativo inclui lógica para lidar com descobertos bancários. Se o saldo da conta corrente for insuficiente para uma transação, o aplicativo verifica a conta poupança para cobrir a diferença. Se o saldo combinado for suficiente, o sistema transfere o valor necessário para a conta corrente e conclui a transação.
Para exemplos de código, você pode consultar diretamente o vídeo de Tim Corey, onde ele explica o código de 3:18 a 18:27.
Evento: Clique no botão
Nesta seção, Tim Corey explorou o funcionamento dos eventos de clique de botão no Windows Forms, explicando como esses eventos são conectados e como funcionam.
Entendendo os eventos de clique de botão
Tim começa explicando o conceito familiar de eventos de clique de botão em aplicativos Windows Forms. Ao clicar duas vezes em um botão no designer, o Visual Studio gera automaticamente um método de tratamento de eventos para o evento de clique.
-
Método de tratamento de eventos :
- Este método é chamado sempre que o botão é clicado. É onde você coloca o código que deve ser executado em resposta ao clique do botão.
private void recordTransactionButton_Click(object sender, EventArgs e) { // Code to handle the button click event }private void recordTransactionButton_Click(object sender, EventArgs e) { // Code to handle the button click event } -
Preparando a fiação para o evento :
- O método de tratamento de eventos está associado ao evento de clique do botão no arquivo de design do formulário (FormName.Designer.cs). Isso é feito usando o operador += para adicionar o manipulador de eventos ao evento de clique do botão.
this.recordTransactionButton.Click += new System.EventHandler(this.recordTransactionButton_Click);this.recordTransactionButton.Click += new System.EventHandler(this.recordTransactionButton_Click);
Criando e invocando eventos personalizados
Tim explica como criar eventos personalizados em C#, começando pela classe Account, onde os eventos serão acionados.
-
Definindo um evento :
Um evento é definido usando a palavra-chave
event. Parece semelhante a uma variável pública, mas é específica para eventos.public event EventHandler<string> RaiseTransactionApprovedEvent;public event EventHandler<string> RaiseTransactionApprovedEvent; -
Acionando o evento :
Os eventos são acionados usando o método Invoke, normalmente dentro da classe que define o evento. O método Invoke recebe dois parâmetros: o remetente (geralmente
this) e os dados do evento (neste caso, uma string).private void OnTransactionApproved(string transactionName) { RaiseTransactionApprovedEvent?.Invoke(this, transactionName); }private void OnTransactionApproved(string transactionName) { RaiseTransactionApprovedEvent?.Invoke(this, transactionName); } -
Conexão e gerenciamento de eventos :
- Inscreva-se no evento usando o operador += e defina um método para lidar com o evento quando ele for acionado.
account.RaiseTransactionApprovedEvent += Account_RaiseTransactionApprovedEvent; private void Account_RaiseTransactionApprovedEvent(object sender, string e) { // Code to handle the event }account.RaiseTransactionApprovedEvent += Account_RaiseTransactionApprovedEvent; private void Account_RaiseTransactionApprovedEvent(object sender, string e) { // Code to handle the event }
Utilizando eventos para atualizar a interface do usuário
Tim explica como usar eventos para atualizar automaticamente a interface do usuário do navegador quando determinadas ações ocorrem, como quando uma transação é aprovada.
-
Eventos de arrecadação de fundos :
- Acione o evento personalizado após a aprovação de uma transação.
public void AddDeposit(decimal amount, string depositName) { // Code to add deposit RaiseTransactionApprovedEvent?.Invoke(this, depositName); }public void AddDeposit(decimal amount, string depositName) { // Code to add deposit RaiseTransactionApprovedEvent?.Invoke(this, depositName); } -
Inscrição em eventos na interface do usuário :
- Inscreva-se no evento no formulário principal para atualizar a lista de transações sempre que uma nova transação for aprovada.
public MainForm() { InitializeComponent(); account.RaiseTransactionApprovedEvent += Account_RaiseTransactionApprovedEvent; } private void Account_RaiseTransactionApprovedEvent(object sender, string e) { // Update the UI with the new transaction }public MainForm() { InitializeComponent(); account.RaiseTransactionApprovedEvent += Account_RaiseTransactionApprovedEvent; } private void Account_RaiseTransactionApprovedEvent(object sender, string e) { // Update the UI with the new transaction }
Evento?.Invoke() explicado
Tim Corey explica o uso da sintaxe ?.Invoke() ao disparar eventos em C#. Essa abordagem moderna simplifica o código e garante a segurança de threads.
O operador de ponto de interrogação
O ponto de interrogação (?) antes de Invoke é um operador condicional nulo. Ele verifica se o manipulador de eventos é nulo antes de invocá-lo, evitando possíveis exceções.
-
Abordagem tradicional :
Anteriormente, os desenvolvedores usavam várias linhas de código para verificar se o manipulador de eventos era nulo e, em seguida, invocá-lo.
if (RaiseTransactionApprovedEvent != null) { RaiseTransactionApprovedEvent(this, depositName); }if (RaiseTransactionApprovedEvent != null) { RaiseTransactionApprovedEvent(this, depositName); } -
Abordagem moderna com ?.Invoke():
O operador condicional nulo simplifica esse processo, realizando a verificação de nulo e invocando o evento em uma única linha.
RaiseTransactionApprovedEvent?.Invoke(this, depositName);RaiseTransactionApprovedEvent?.Invoke(this, depositName);- Se
RaiseTransactionApprovedEventfor nulo, a invocação não prossegue, evitando efetivamente quaisquer exceções.
- Se
-
Benefícios :
- Simplifica o código : Reduz a quantidade de código necessária para invocar eventos com segurança.
- Segurança de Threads : Elimina condições de corrida verificando se o valor é nulo e invocando o evento em uma única etapa.
Ouvir e escrever código para o evento
Tim explica como monitorar eventos personalizados em um aplicativo Windows Forms e atualizar a interface do usuário de acordo.
-
Inscrição em eventos :
- Inscreva-se no evento personalizado usando o operador +=.
customer.CheckingAccount.TransactionApprovedEvent += CheckingAccount_TransactionApprovedEvent;customer.CheckingAccount.TransactionApprovedEvent += CheckingAccount_TransactionApprovedEvent; -
Método de tratamento de eventos :
- Defina um método para lidar com o evento. Este método atualiza a interface do usuário com base nos dados do evento.
private void CheckingAccount_TransactionApprovedEvent(object sender, string e) { // Update the UI with the new transaction checkingTransactionsDataSource.DataSource = null; checkingTransactionsDataSource.DataSource = customer.CheckingAccount.Transactions; checkingBalanceLabel.Text = customer.CheckingAccount.Balance.ToString("C2"); }private void CheckingAccount_TransactionApprovedEvent(object sender, string e) { // Update the UI with the new transaction checkingTransactionsDataSource.DataSource = null; checkingTransactionsDataSource.DataSource = customer.CheckingAccount.Transactions; checkingBalanceLabel.Text = customer.CheckingAccount.Balance.ToString("C2"); }
Criando um evento personalizado: o evento em ação e um resumo.
Tim demonstra todo o processo de criação, organização e gestão de eventos personalizados na prática.
-
Acionando o evento :
- Acione o evento após a aprovação de uma transação ou quando o saldo for alterado.
private void OnTransactionApproved(string transactionName) { RaiseTransactionApprovedEvent?.Invoke(this, transactionName); }private void OnTransactionApproved(string transactionName) { RaiseTransactionApprovedEvent?.Invoke(this, transactionName); } -
Gerenciamento de múltiplos eventos :
- Garantir que o aplicativo escute vários eventos, como transações e alterações de saldo, para manter a interface do usuário atualizada em tempo real.
public MainForm() { InitializeComponent(); customer.CheckingAccount.TransactionApprovedEvent += CheckingAccount_TransactionApprovedEvent; customer.SavingsAccount.TransactionApprovedEvent += SavingsAccount_TransactionApprovedEvent; } private void SavingsAccount_TransactionApprovedEvent(object sender, string e) { // Update the UI with the new savings transaction savingsTransactionsDataSource.DataSource = null; savingsTransactionsDataSource.DataSource = customer.SavingsAccount.Transactions; savingsBalanceLabel.Text = customer.SavingsAccount.Balance.ToString("C2"); }public MainForm() { InitializeComponent(); customer.CheckingAccount.TransactionApprovedEvent += CheckingAccount_TransactionApprovedEvent; customer.SavingsAccount.TransactionApprovedEvent += SavingsAccount_TransactionApprovedEvent; } private void SavingsAccount_TransactionApprovedEvent(object sender, string e) { // Update the UI with the new savings transaction savingsTransactionsDataSource.DataSource = null; savingsTransactionsDataSource.DataSource = customer.SavingsAccount.Transactions; savingsBalanceLabel.Text = customer.SavingsAccount.Balance.ToString("C2"); } -
Executando o aplicativo :
Tim executa o aplicativo para demonstrar como a interface do usuário é atualizada automaticamente com base em eventos acionados por transações.
Informações sobre os argumentos do evento: Depuração
Tim mostra como depurar eventos e inspecionar as informações enviadas com eles.
-
Definindo um ponto de interrupção :
- Defina um ponto de interrupção no método de tratamento de eventos para inspecionar os dados do evento.
private void CheckingAccount_TransactionApprovedEvent(object sender, string e) { // Breakpoint here }private void CheckingAccount_TransactionApprovedEvent(object sender, string e) { // Breakpoint here } -
Depuração :
- Execute o aplicativo e realize uma transação para acionar o evento. Inspecione os argumentos do evento no depurador. O parâmetro "sender" fornece a instância que gerou o evento, e o parâmetro "e" contém os dados do evento.
Criando outro evento personalizado (evento de sobregiro)
Tim Corey expande a demonstração criando outro evento personalizado para lidar com situações de sobregiro. Este evento será acionado quando ocorrer um saldo negativo na conta e notificará o usuário sobre o valor do saldo negativo.
Definindo o evento de sobregiro
Tim começa definindo um novo evento na classe Account para cenários de descoberto:
-
Declaração do evento :
- Defina o evento usando a palavra-chave
eventcom um tipo decimal para passar o valor do saldo negativo.
public event EventHandler<decimal> OverdraftEvent;public event EventHandler<decimal> OverdraftEvent; - Defina o evento usando a palavra-chave
-
Acionando o evento :
O evento é acionado na parte do código onde ocorre um estouro de saldo com sucesso.
if (overdraftSuccessful) { OverdraftEvent?.Invoke(this, overdraftAmount); }if (overdraftSuccessful) { OverdraftEvent?.Invoke(this, overdraftAmount); }
Assinar o evento de sobregiro no painel de controle.
-
Preparando a fiação para o evento :
- Inscreva-se no alerta de sobregiro no formulário do Painel de Controle.
customer.CheckingAccount.OverdraftEvent += CheckingAccount_OverdraftEvent;customer.CheckingAccount.OverdraftEvent += CheckingAccount_OverdraftEvent; -
Gerenciamento do Evento :
- Defina um manipulador de eventos para exibir uma mensagem quando ocorrer um saldo negativo na conta.
private void CheckingAccount_OverdraftEvent(object sender, decimal e) { errorMessage.Text = $"You had an overdraft protection transfer of {e:C2}"; errorMessage.Visible = true; }private void CheckingAccount_OverdraftEvent(object sender, decimal e) { errorMessage.Text = $"You had an overdraft protection transfer of {e:C2}"; errorMessage.Visible = true; } -
Acionando e exibindo o evento :
- Quando ocorre um saldo negativo na conta, o evento é acionado e atualiza a interface do usuário para notificar o usuário.
You had an overdraft protection transfer of $20.44
Ouvir o evento em vários locais
Tim explica como ouvir o mesmo evento em vários idiomas e formatos, demonstrando a versatilidade dos eventos.
-
Adicionando um rótulo a outro formulário :
- Adicione um rótulo a um formulário secundário para exibir mensagens de sobregiro.
<asp:Label ID="errorMessage" runat="server" Visible="false" /><asp:Label ID="errorMessage" runat="server" Visible="false" />HTML -
Inscrição no evento :
- Subscreva o evento de descoberto no formulário secundário.
customer.CheckingAccount.OverdraftEvent += SecondaryForm_OverdraftEvent;customer.CheckingAccount.OverdraftEvent += SecondaryForm_OverdraftEvent; -
Gerenciamento do Evento :
- Defina um manipulador de eventos para exibir a mensagem de saldo negativo no formulário secundário.
private void SecondaryForm_OverdraftEvent(object sender, decimal e) { errorMessage.Visible = true; }private void SecondaryForm_OverdraftEvent(object sender, decimal e) { errorMessage.Visible = true; } -
Tratamento simultâneo de eventos :
Tim demonstra que o evento pode ser tratado de múltiplas formas simultaneamente, garantindo que todas as partes relevantes da aplicação respondam ao evento de forma adequada.
Both the main form and the secondary form display the overdraft message when the event is triggered.
Removendo ouvintes de eventos da memória
Tim destaca a importância de limpar os listeners de eventos para evitar vazamentos de memória e garantir o desempenho adequado do aplicativo.
-
Cancelar inscrição em eventos :
É crucial cancelar a inscrição em eventos antes de destruir uma instância de classe ou fechar um formulário.
customer.CheckingAccount.OverdraftEvent -= CheckingAccount_OverdraftEvent;customer.CheckingAccount.OverdraftEvent -= CheckingAccount_OverdraftEvent;Por que isso é importante :
- Não cancelar a inscrição em eventos pode causar vazamentos de memória, pois os objetos que estão escutando eventos podem não ser coletados corretamente pelo coletor de lixo.
-
Utilizando Métodos Nomeados :
- Evite usar funções anônimas para manipuladores de eventos, pois isso dificulta o cancelamento da inscrição nos eventos.
// Good practice: using named methods for event handlers// Good practice: using named methods for event handlers
Manipulador de eventos genérico: passando uma classe para T
Tim Corey explica as melhores práticas para transmitir dados por meio de eventos, em particular os benefícios de usar uma classe em vez de tipos de dados simples como string ou decimal.
Por que usar uma classe para dados de eventos?
Tim começa por discutir por que o uso de tipos de dados simples para eventos é menos comum e por que geralmente é melhor passar uma classe:
-
Flexibilidade e escalabilidade :
- O uso de uma classe permite que você passe vários dados relacionados por meio de um evento. Se precisar adicionar mais dados posteriormente, você pode simplesmente estender a classe sem alterar a assinatura do evento.
-
Herança de EventArgs :
- Embora antes fosse necessário que qualquer objeto passado por um evento herdasse de EventArgs, isso não é mais obrigatório. No entanto, herdar de EventArgs ainda pode ser benéfico para consistência e clareza.
Criando a classe EventArgs de sobregiro
Tim demonstra como criar uma classe EventArgs personalizada para o evento de sobregiro.
-
Defina a classe :
- Crie uma nova classe que herde de EventArgs e inclua propriedades para os dados que você deseja passar pelo evento.
public class OverdraftEventArgs : EventArgs { public decimal AmountOverdrafted { get; private set; } public string MoreInfo { get; private set; } public OverdraftEventArgs(decimal amountOverdrafted, string moreInfo) { AmountOverdrafted = amountOverdrafted; MoreInfo = moreInfo; } }public class OverdraftEventArgs : EventArgs { public decimal AmountOverdrafted { get; private set; } public string MoreInfo { get; private set; } public OverdraftEventArgs(decimal amountOverdrafted, string moreInfo) { AmountOverdrafted = amountOverdrafted; MoreInfo = moreInfo; } } -
Utilizando a classe no evento :
- Atualize a declaração do evento para usar a classe personalizada EventArgs.
public event EventHandler<OverdraftEventArgs> OverdraftEvent;public event EventHandler<OverdraftEventArgs> OverdraftEvent; -
Acionando o evento :
- Ao invocar o evento, passe uma instância da classe EventArgs personalizada.
OverdraftEvent?.Invoke(this, new OverdraftEventArgs(amountNeeded, "Additional info"));OverdraftEvent?.Invoke(this, new OverdraftEventArgs(amountNeeded, "Additional info"));
Importância das propriedades somente leitura
Tim enfatiza a importância de usar propriedades somente leitura na classe EventArgs para evitar a modificação acidental dos dados do evento.
-
Evitar modificações :
- Se as propriedades da classe EventArgs tiverem métodos setters públicos, qualquer manipulador de eventos poderá modificar os dados, o que pode levar a comportamentos inesperados.
- O uso de métodos setters privados e a inicialização de propriedades por meio do construtor garantem que os dados do evento permaneçam consistentes.
-
Exemplo do problema :
Tim demonstra como a modificação dos dados de um evento em um manipulador de eventos pode afetar outros manipuladores se as propriedades não forem somente leitura.
private void CheckingAccount_OverdraftEvent(object sender, OverdraftEventArgs e) { e.AmountOverdrafted = 1000; // This modification affects all handlers }private void CheckingAccount_OverdraftEvent(object sender, OverdraftEventArgs e) { e.AmountOverdrafted = 1000; // This modification affects all handlers } -
Solução :
- Utilize métodos setters privados e passe dados através do construtor para tornar as propriedades somente leitura.
public decimal AmountOverdrafted { get; private set; } public string MoreInfo { get; private set; }public decimal AmountOverdrafted { get; private set; } public string MoreInfo { get; private set; }
Exceção Quando usar o conjunto público (59:29)
Tim Corey destaca uma importante exceção à regra de usar métodos setters privados para propriedades de dados de eventos. Essa exceção ocorre quando é necessário permitir que os ouvintes de eventos modifiquem os dados do evento, como nos casos em que uma transação pode ser cancelada com base em determinadas condições.
Exemplo: Cancelamento de uma transação
Tim fornece um exemplo em que um manipulador de eventos pode precisar cancelar uma transação. Isso é conseguido adicionando uma propriedade CancelTransaction à classe EventArgs personalizada.
-
Definindo a propriedade :
- Adicione uma propriedade pública com métodos getter e setter à classe EventArgs.
public class OverdraftEventArgs : EventArgs { public decimal AmountOverdrafted { get; private set; } public string MoreInfo { get; private set; } public bool CancelTransaction { get; set; } = false; public OverdraftEventArgs(decimal amountOverdrafted, string moreInfo) { AmountOverdrafted = amountOverdrafted; MoreInfo = moreInfo; } }public class OverdraftEventArgs : EventArgs { public decimal AmountOverdrafted { get; private set; } public string MoreInfo { get; private set; } public bool CancelTransaction { get; set; } = false; public OverdraftEventArgs(decimal amountOverdrafted, string moreInfo) { AmountOverdrafted = amountOverdrafted; MoreInfo = moreInfo; } } -
Definindo a propriedade no manipulador de eventos :
- No painel de controle, o manipulador de eventos pode definir essa propriedade para cancelar a transação.
private void CheckingAccount_OverdraftEvent(object sender, OverdraftEventArgs e) { if (denyOverdraft.Checked) { e.CancelTransaction = true; } errorMessage.Text = $"You had an overdraft protection transfer of {e.AmountOverdrafted:C2}"; errorMessage.Visible = true; }private void CheckingAccount_OverdraftEvent(object sender, OverdraftEventArgs e) { if (denyOverdraft.Checked) { e.CancelTransaction = true; } errorMessage.Text = $"You had an overdraft protection transfer of {e.AmountOverdrafted:C2}"; errorMessage.Visible = true; } -
Verificando a propriedade no método de origem :
- No método que dispara o evento, verifique se a propriedade CancelTransaction está definida como verdadeira antes de prosseguir.
if (args.CancelTransaction) { return false; // Transaction is canceled }if (args.CancelTransaction) { return false; // Transaction is canceled }
Tornando o aplicativo mais interativo
Tim aprimora ainda mais o aplicativo para torná-lo mais interativo e fácil de usar.
-
Adicionando uma caixa de seleção para controle de sobregiro :
- Adicione uma caixa de seleção ao formulário que permita ao usuário ativar ou desativar a proteção contra sobregiro.
private void InitializeComponent() { this.denyOverdraft = new System.Windows.Forms.CheckBox(); // Initialize other controls this.denyOverdraft.Text = "Stop Overdrafts"; this.denyOverdraft.CheckedChanged += new System.EventHandler(this.denyOverdraft_CheckedChanged); }private void InitializeComponent() { this.denyOverdraft = new System.Windows.Forms.CheckBox(); // Initialize other controls this.denyOverdraft.Text = "Stop Overdrafts"; this.denyOverdraft.CheckedChanged += new System.EventHandler(this.denyOverdraft_CheckedChanged); } -
Gerenciando o estado da caixa de seleção :
- No manipulador de eventos da caixa de seleção, atualize a lógica para considerar o estado da caixa de seleção ao decidir cancelar uma transação.
private void denyOverdraft_CheckedChanged(object sender, EventArgs e) { if (denyOverdraft.Checked) { // Logic to stop overdraft transactions } }private void denyOverdraft_CheckedChanged(object sender, EventArgs e) { if (denyOverdraft.Checked) { // Logic to stop overdraft transactions } } -
Atualizando o manipulador de eventos :
- Garantir que o manipulador de eventos respeite o estado da caixa de seleção para permitir ou negar o uso do limite de crédito.
private void CheckingAccount_OverdraftEvent(object sender, OverdraftEventArgs e) { if (denyOverdraft.Checked) { e.CancelTransaction = true; } errorMessage.Text = $"You had an overdraft protection transfer of {e.AmountOverdrafted:C2}"; errorMessage.Visible = true; }private void CheckingAccount_OverdraftEvent(object sender, OverdraftEventArgs e) { if (denyOverdraft.Checked) { e.CancelTransaction = true; } errorMessage.Text = $"You had an overdraft protection transfer of {e.AmountOverdrafted:C2}"; errorMessage.Visible = true; }
Resumo
Tim Corey conclui o tutorial resumindo os pontos principais e as melhores práticas para trabalhar com eventos em C#.
-
Remover ouvintes de eventos :
- Sempre remova os ouvintes de eventos antes de destruir objetos para evitar vazamentos de memória.
- Use o operador -= para cancelar a inscrição em eventos.
customer.CheckingAccount.OverdraftEvent -= CheckingAccount_OverdraftEvent;customer.CheckingAccount.OverdraftEvent -= CheckingAccount_OverdraftEvent; -
Usar a herança de EventArgs:
Embora não seja obrigatório, herdar de EventArgs pode ser benéfico para consistência e para usar recursos integrados como EventArgs.Empty.
-
Definidores privados para propriedades somente leitura :
- Utilize métodos setters privados para evitar modificações não intencionais nos dados do evento. Permita o uso de métodos setters públicos somente quando necessário, como em transações canceláveis.
-
Sintaxe do manipulador de eventos :
- Use o delegado EventHandler para definir eventos, fornecendo um padrão claro e consistente para passagem de dados de eventos.
-
Operador condicional nulo :
- Use o operador condicional nulo (?.Invoke()) para invocar eventos com segurança, sem correr o risco de exceções de referência nula.
Conclusão
O tutorial completo de Tim Corey sobre eventos em C# oferece informações valiosas e exemplos práticos para criar, manipular e gerenciar eventos de forma eficaz. Seguindo essas boas práticas, os desenvolvedores podem criar aplicativos mais interativos e responsivos.
