Earn More by Sharing What You Love
Do you create content for developers working with .NET, C#, Java, Python, or Node.js? Turn your expertise into extra income!

Tim Corey
1h 9m 13s
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.
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.
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 :
Formulário principal :
Formulário de Transação :
Tim explica o código de backend do aplicativo bancário de demonstração:
Classe de Cliente :
Classe da conta :
Gerenciamento de depósitos e pagamentos :
Proteção contra sobregiro :
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.
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.
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 :
private void recordTransactionButton_Click(object sender, EventArgs e)
{
// Code to handle the button click event
}
Preparando a fiação para o evento :
this.recordTransactionButton.Click += new System.EventHandler(this.recordTransactionButton_Click);AddHandler Me.recordTransactionButton.Click, AddressOf Me.recordTransactionButton_ClickTim 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 RaiseTransactionApprovedEvent As EventHandler(Of String)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 aceita dois parâmetros: o remetente (geralmente this) e dados de evento (neste caso, uma string).
private void OnTransactionApproved(string transactionName)
{
RaiseTransactionApprovedEvent?.Invoke(this, transactionName);
}
Conexão e gerenciamento de eventos :
account.RaiseTransactionApprovedEvent += Account_RaiseTransactionApprovedEvent;
private void Account_RaiseTransactionApprovedEvent(object sender, string e)
{
// Code to handle the event
}
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 :
public void AddDeposit(decimal amount, string depositName)
{
// Code to add deposit
RaiseTransactionApprovedEvent?.Invoke(this, depositName);
}
Inscrição em eventos na interface do usuário :
public MainForm()
{
InitializeComponent();
account.RaiseTransactionApprovedEvent += Account_RaiseTransactionApprovedEvent;
}
private void Account_RaiseTransactionApprovedEvent(object sender, string e)
{
// Update the UI with the new transaction
}
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 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);
}
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(Me, depositName)RaiseTransactionApprovedEvent for nulo, a invocação não prossegue, efetivamente evitando quaisquer exceções.Benefícios :
Tim explica como monitorar eventos personalizados em um aplicativo Windows Forms e atualizar a interface do usuário de acordo.
Inscrição em eventos :
customer.CheckingAccount.TransactionApprovedEvent += CheckingAccount_TransactionApprovedEvent;AddHandler customer.CheckingAccount.TransactionApprovedEvent, AddressOf CheckingAccount_TransactionApprovedEventMétodo de tratamento de eventos :
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");
}
Tim demonstra todo o processo de criação, organização e gestão de eventos personalizados na prática.
Acionando o evento :
private void OnTransactionApproved(string transactionName)
{
RaiseTransactionApprovedEvent?.Invoke(this, transactionName);
}
Gerenciamento de múltiplos eventos :
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.
Tim mostra como depurar eventos e inspecionar as informações enviadas com eles.
Definindo um ponto de interrupção :
private void CheckingAccount_TransactionApprovedEvent(object sender, string e)
{
// Breakpoint here
}
Depuração :
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.
Tim começa definindo um novo evento na classe Account para cenários de descoberto:
Declaração do evento :
event com um tipo decimal para passar o valor do saldo negativo.public event EventHandler<decimal> OverdraftEvent;Public Event OverdraftEvent As EventHandler(Of Decimal)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);
}
Preparando a fiação para o evento :
customer.CheckingAccount.OverdraftEvent += CheckingAccount_OverdraftEvent;AddHandler customer.CheckingAccount.OverdraftEvent, AddressOf CheckingAccount_OverdraftEventGerenciamento do Evento :
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 :
You had an overdraft protection transfer of $20.44
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 :
<asp:Label ID="errorMessage" runat="server" Visible="false" />
Inscrição no evento :
customer.CheckingAccount.OverdraftEvent += SecondaryForm_OverdraftEvent;AddHandler customer.CheckingAccount.OverdraftEvent, AddressOf SecondaryForm_OverdraftEventGerenciamento do Evento :
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.
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;RemoveHandler customer.CheckingAccount.OverdraftEvent, AddressOf CheckingAccount_OverdraftEventPor que isso é importante :
Utilizando Métodos Nomeados :
// Good practice: using named methods for event handlers' Good practice: using named methods for event handlersTim 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.
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 :
Herança de EventArgs :
Tim demonstra como criar uma classe EventArgs personalizada para o evento de sobregiro.
Defina a classe :
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 :
public event EventHandler<OverdraftEventArgs> OverdraftEvent;Public Event OverdraftEvent As EventHandler(Of OverdraftEventArgs)Acionando o evento :
OverdraftEvent?.Invoke(this, new OverdraftEventArgs(amountNeeded, "Additional info"));OverdraftEvent?.Invoke(Me, New OverdraftEventArgs(amountNeeded, "Additional info"))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 :
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
}
Solução :
public decimal AmountOverdrafted { get; private set; }
public string MoreInfo { get; private set; }
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.
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 :
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 :
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 :
if (args.CancelTransaction)
{
return false; // Transaction is canceled
}
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 :
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 :
private void denyOverdraft_CheckedChanged(object sender, EventArgs e)
{
if (denyOverdraft.Checked)
{
// Logic to stop overdraft transactions
}
}
Atualizando o manipulador de eventos :
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;
}
Tim Corey conclui o tutorial resumindo os pontos principais e as melhores práticas para trabalhar com eventos em C#.
Remover ouvintes de eventos :
customer.CheckingAccount.OverdraftEvent -= CheckingAccount_OverdraftEvent;RemoveHandler customer.CheckingAccount.OverdraftEvent, AddressOf CheckingAccount_OverdraftEventUsar 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 :
Sintaxe do manipulador de eventos :
Operador condicional nulo :
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.
Do you create content for developers working with .NET, C#, Java, Python, or Node.js? Turn your expertise into extra income!
Join our newsletter, you’ll get exclusive access on article updates. We value your privacy