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
Los eventos en C# son un concepto fundamental que muchos desarrolladores utilizan pero que quizá no entiendan del todo, sobre todo cuando se trata de crear sus propios eventos. Tim Corey ofrece una guía completa sobre cómo crear y utilizar eventos, explorando las mejores prácticas y características avanzadas en su vídeo "C# Events - Creating and Consuming Events in Your Application".
En este artículo, vamos a explorar los eventos de C#, centrándonos en su sintaxis, cómo se definen y cómo ayudan a resolver problemas comunes de programación utilizando los ejemplos en vídeo de Tim Corey. Comprender la gestión de eventos en C# es esencial para crear aplicaciones con capacidad de respuesta, y este artículo le ayudará a comprender los conceptos básicos del registro de errores personalizado, la gestión de excepciones y la programación basada en eventos.
En C# y en los lenguajes de programación, los eventos desempeñan un papel fundamental en la programación basada en eventos, ya que permiten a las aplicaciones responder a acciones como interacciones del usuario o cambios en el sistema. En comparación con otros lenguajes de programación, C# ofrece un enfoque estructurado para el manejo de eventos, lo que lo hace ideal para aplicaciones rápidas y pequeñas. Los eventos en C# se desencadenan mediante acciones específicas, y estas acciones invocan a los manejadores de eventos correspondientes para realizar las tareas deseadas.
Tim comienza explicando que la mayoría de los desarrolladores están familiarizados con los eventos en C#, pero pueden no saber cómo crear eventos personalizados. El objetivo del vídeo es presentar los eventos, explicar cómo crear eventos personalizados, hablar de sus características y describir las mejores prácticas.
Tim utiliza una sencilla aplicación bancaria construida con Windows Forms (WinForms) para demostrar los eventos. La aplicación simula las operaciones bancarias básicas de un cliente, incluida la consulta de saldos y el registro de transacciones.
Resumen de la aplicación:
Formato principal:
Formulario de transacción:
Tim explica el código backend de la aplicación bancaria de demostración:
Clase de cliente:
Clase de cuenta:
Gestión de depósitos y pagos:
Protección contra sobregiros:
Para ver ejemplos de código, puede consultar directamente el vídeo de Tim Corey en el que explica el código desde el minuto 3:18 hasta el 18:27.
En esta sección, Tim Corey se sumergió en el funcionamiento de los eventos de clic de botón en Windows Forms, explicando cómo se conectan estos eventos y cómo funcionan.
Tim comienza explicando el concepto familiar de eventos de clic de botón en aplicaciones Windows Forms. Al hacer doble clic en un botón del diseñador, Visual Studio genera automáticamente un método controlador de eventos para el evento de clic.
Método de gestión de eventos:
private void recordTransactionButton_Click(object sender, EventArgs e)
{
// Code to handle the button click event
}Private Sub recordTransactionButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles recordTransactionButton.Click
' Code to handle the button click event
End SubCableado del evento :
this.recordTransactionButton.Click += new System.EventHandler(this.recordTransactionButton_Click);AddHandler Me.recordTransactionButton.Click, AddressOf Me.recordTransactionButton_ClickTim explica cómo crear eventos personalizados en C#, empezando por la clase Account, donde se activarán los eventos.
Definición de un evento:
public event EventHandler<string> RaiseTransactionApprovedEvent;Public Event RaiseTransactionApprovedEvent As EventHandler(Of String)Desencadenante del evento:
this) y los datos del evento (en este caso, una cadena).private void OnTransactionApproved(string transactionName)
{
RaiseTransactionApprovedEvent?.Invoke(this, transactionName);
}Private Sub OnTransactionApproved(ByVal transactionName As String)
RaiseTransactionApprovedEvent?.Invoke(Me, transactionName)
End SubCableado y manejo de eventos:
account.RaiseTransactionApprovedEvent += Account_RaiseTransactionApprovedEvent;
private void Account_RaiseTransactionApprovedEvent(object sender, string e)
{
// Code to handle the event
}AddHandler account.RaiseTransactionApprovedEvent, AddressOf Account_RaiseTransactionApprovedEvent
Private Sub Account_RaiseTransactionApprovedEvent(sender As Object, e As String)
' Code to handle the event
End SubTim explica cómo utilizar eventos para actualizar automáticamente la interfaz de usuario del navegador cuando se producen determinadas acciones, como la aprobación de una transacción.
Eventos de recaudación:
public void AddDeposit(decimal amount, string depositName)
{
// Code to add deposit
RaiseTransactionApprovedEvent?.Invoke(this, depositName);
}Public Sub AddDeposit(ByVal amount As Decimal, ByVal depositName As String)
' Code to add deposit
RaiseTransactionApprovedEvent?.Invoke(Me, depositName)
End SubSuscripción a eventos en la interfaz de usuario:
public MainForm()
{
InitializeComponent();
account.RaiseTransactionApprovedEvent += Account_RaiseTransactionApprovedEvent;
}
private void Account_RaiseTransactionApprovedEvent(object sender, string e)
{
// Update the UI with the new transaction
}Public Sub New()
InitializeComponent()
AddHandler account.RaiseTransactionApprovedEvent, AddressOf Account_RaiseTransactionApprovedEvent
End Sub
Private Sub Account_RaiseTransactionApprovedEvent(sender As Object, e As String)
' Update the UI with the new transaction
End SubTim Corey explica el uso de la sintaxis ?.Invoke() al lanzar eventos en C#. Este enfoque moderno simplifica el código y garantiza la seguridad de los hilos.
El signo de interrogación (?.) delante de Invoke es un operador de condición nula. Comprueba si el manejador de eventos es nulo antes de invocarlo, evitando posibles excepciones.
Enfoque tradicional:
if (RaiseTransactionApprovedEvent != null)
{
RaiseTransactionApprovedEvent(this, depositName);
}If RaiseTransactionApprovedEvent IsNot Nothing Then
RaiseTransactionApprovedEvent(Me, depositName)
End If**Enfoque moderno con **.Invoke():
RaiseTransactionApprovedEvent?.Invoke(this, depositName);RaiseTransactionApprovedEvent?.Invoke(Me, depositName)RaiseTransactionApprovedEvent es nulo, la invocación no procede, evitando efectivamente cualquier excepción.Beneficios:
Tim explica cómo escuchar eventos personalizados en una aplicación Windows Forms y actualizar la interfaz de usuario en consecuencia.
Suscripción a eventos:
customer.CheckingAccount.TransactionApprovedEvent += CheckingAccount_TransactionApprovedEvent;AddHandler customer.CheckingAccount.TransactionApprovedEvent, AddressOf CheckingAccount_TransactionApprovedEventMétodo de gestión 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");
}Private Sub CheckingAccount_TransactionApprovedEvent(sender As Object, e As String)
' Update the UI with the new transaction
checkingTransactionsDataSource.DataSource = Nothing
checkingTransactionsDataSource.DataSource = customer.CheckingAccount.Transactions
checkingBalanceLabel.Text = customer.CheckingAccount.Balance.ToString("C2")
End SubTim muestra en acción todo el proceso de creación, activación y gestión de eventos personalizados.
Desencadenante del evento:
private void OnTransactionApproved(string transactionName)
{
RaiseTransactionApprovedEvent?.Invoke(this, transactionName);
}Private Sub OnTransactionApproved(ByVal transactionName As String)
RaiseTransactionApprovedEvent?.Invoke(Me, transactionName)
End SubManejo de múltiples 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");
}Public Sub New()
InitializeComponent()
AddHandler customer.CheckingAccount.TransactionApprovedEvent, AddressOf CheckingAccount_TransactionApprovedEvent
AddHandler customer.SavingsAccount.TransactionApprovedEvent, AddressOf SavingsAccount_TransactionApprovedEvent
End Sub
Private Sub SavingsAccount_TransactionApprovedEvent(sender As Object, e As String)
' Update the UI with the new savings transaction
savingsTransactionsDataSource.DataSource = Nothing
savingsTransactionsDataSource.DataSource = customer.SavingsAccount.Transactions
savingsBalanceLabel.Text = customer.SavingsAccount.Balance.ToString("C2")
End SubEjecución de la aplicación:
Tim muestra cómo depurar eventos e inspeccionar la información que se envía con ellos.
Cómo establecer un punto de interrupción:
private void CheckingAccount_TransactionApprovedEvent(object sender, string e)
{
// Breakpoint here
}Private Sub CheckingAccount_TransactionApprovedEvent(ByVal sender As Object, ByVal e As String)
' Breakpoint here
End SubDepuración :
Tim Corey amplía la demostración creando otro evento personalizado para gestionar situaciones de descubierto. Este evento se activará cuando se produzca un descubierto y notificará al usuario el importe del mismo.
Tim comienza definiendo un nuevo evento en la clase Cuenta para escenarios de sobregiro:
Declaración de eventos:
public event EventHandler<decimal> OverdraftEvent;Public Event OverdraftEvent As EventHandler(Of Decimal)Desencadenante del evento:
if (overdraftSuccessful)
{
OverdraftEvent?.Invoke(this, overdraftAmount);
}If overdraftSuccessful Then
RaiseEvent OverdraftEvent(Me, overdraftAmount)
End IfCableado del evento :
customer.CheckingAccount.OverdraftEvent += CheckingAccount_OverdraftEvent;AddHandler customer.CheckingAccount.OverdraftEvent, AddressOf CheckingAccount_OverdraftEventGestión del evento:
private void CheckingAccount_OverdraftEvent(object sender, decimal e)
{
errorMessage.Text = $"You had an overdraft protection transfer of {e:C2}";
errorMessage.Visible = true;
}Private Sub CheckingAccount_OverdraftEvent(sender As Object, e As Decimal)
errorMessage.Text = $"You had an overdraft protection transfer of {e:C2}"
errorMessage.Visible = True
End SubDesencadenamiento y visualización del evento:
You had an overdraft protection transfer of $20.44
Tim explica cómo escuchar el mismo evento en varios idiomas y formas, demostrando la versatilidad de los eventos.
Añadir una etiqueta a otro formulario:
<asp:Label ID="errorMessage" runat="server" Visible="false" />
Suscripción al evento:
customer.CheckingAccount.OverdraftEvent += SecondaryForm_OverdraftEvent;AddHandler customer.CheckingAccount.OverdraftEvent, AddressOf SecondaryForm_OverdraftEventGestión del evento:
private void SecondaryForm_OverdraftEvent(object sender, decimal e)
{
errorMessage.Visible = true;
}Private Sub SecondaryForm_OverdraftEvent(sender As Object, e As Decimal)
errorMessage.Visible = True
End SubManejo simultáneo de eventos:
Both the main form and the secondary form display the overdraft message when the event is triggered.
Tim destaca la importancia de limpiar los escuchadores de eventos para evitar fugas de memoria y garantizar un rendimiento adecuado de la aplicación.
Desuscripción de eventos:
customer.CheckingAccount.OverdraftEvent -= CheckingAccount_OverdraftEvent;RemoveHandler customer.CheckingAccount.OverdraftEvent, AddressOf CheckingAccount_OverdraftEventPor qué es importante:
Uso de métodos con nombre:
// Good practice: using named methods for event handlers' Good practice: using named methods for event handlersTim Corey explica las mejores prácticas para pasar datos a través de eventos, en particular las ventajas de utilizar una clase en lugar de tipos de datos simples como string o decimal.
Tim comienza explicando por qué es menos habitual utilizar tipos de datos simples para los eventos y por qué suele ser mejor pasar una clase:
Flexibilidad y escalabilidad:
herencia de EventArgs:
Tim demuestra cómo crear una clase EventArgs personalizada para el evento de sobregiro.
Definir la clase:
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
Inherits EventArgs
Public Property AmountOverdrafted As Decimal
Public Property MoreInfo As String
Public Sub New(amountOverdrafted As Decimal, moreInfo As String)
Me.AmountOverdrafted = amountOverdrafted
Me.MoreInfo = moreInfo
End Sub
End ClassUtilización de la clase en el evento:
public event EventHandler<OverdraftEventArgs> OverdraftEvent;Public Event OverdraftEvent As EventHandler(Of OverdraftEventArgs)Desencadenante del evento:
OverdraftEvent?.Invoke(this, new OverdraftEventArgs(amountNeeded, "Additional info"));OverdraftEvent?.Invoke(Me, New OverdraftEventArgs(amountNeeded, "Additional info"))Tim hace hincapié en la importancia de utilizar propiedades de sólo lectura en la clase EventArgs para evitar la modificación accidental de los datos de eventos.
Evitar modificaciones:
Ejemplo del problema:
private void CheckingAccount_OverdraftEvent(object sender, OverdraftEventArgs e)
{
e.AmountOverdrafted = 1000; // This modification affects all handlers
}Private Sub CheckingAccount_OverdraftEvent(sender As Object, e As OverdraftEventArgs)
e.AmountOverdrafted = 1000 ' This modification affects all handlers
End SubSolución:
public decimal AmountOverdrafted { get; private set; }
public string MoreInfo { get; private set; }Public Property AmountOverdrafted As Decimal
Public Property MoreInfo As StringTim Corey destaca una importante excepción a la regla de utilizar definidores privados para las propiedades de datos de eventos. Esta excepción se da cuando es necesario permitir que los oyentes de eventos modifiquen los datos del evento, como en los casos en los que una transacción podría cancelarse en función de ciertas condiciones.
Tim ofrece un ejemplo en el que un controlador de eventos puede tener que cancelar una transacción. Esto se consigue añadiendo una propiedad CancelTransaction a la clase personalizada EventArgs.
Definición de la propiedad:
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
Inherits EventArgs
Public Property AmountOverdrafted As Decimal
Public Property MoreInfo As String
Public Property CancelTransaction As Boolean = False
Public Sub New(amountOverdrafted As Decimal, moreInfo As String)
Me.AmountOverdrafted = amountOverdrafted
Me.MoreInfo = moreInfo
End Sub
End ClassConfiguración de la propiedad en el manejador 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;
}Private Sub CheckingAccount_OverdraftEvent(ByVal sender As Object, ByVal e As OverdraftEventArgs)
If denyOverdraft.Checked Then
e.CancelTransaction = True
End If
errorMessage.Text = $"You had an overdraft protection transfer of {e.AmountOverdrafted:C2}"
errorMessage.Visible = True
End SubComprobación de la propiedad en el método fuente:
if (args.CancelTransaction)
{
return false; // Transaction is canceled
}If args.CancelTransaction Then
Return False ' Transaction is canceled
End IfTim perfecciona la aplicación para hacerla más interactiva y fácil de usar.
Añadir una casilla de verificación para el control de sobregiros:
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 Sub InitializeComponent()
Me.denyOverdraft = New System.Windows.Forms.CheckBox()
' Initialize other controls
Me.denyOverdraft.Text = "Stop Overdrafts"
AddHandler Me.denyOverdraft.CheckedChanged, AddressOf Me.denyOverdraft_CheckedChanged
End SubManejo del estado de las casillas de verificación:
private void denyOverdraft_CheckedChanged(object sender, EventArgs e)
{
if (denyOverdraft.Checked)
{
// Logic to stop overdraft transactions
}
}Private Sub denyOverdraft_CheckedChanged(sender As Object, e As EventArgs) Handles denyOverdraft.CheckedChanged
If denyOverdraft.Checked Then
' Logic to stop overdraft transactions
End If
End SubActualización del controlador 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;
}Private Sub CheckingAccount_OverdraftEvent(ByVal sender As Object, ByVal e As OverdraftEventArgs)
If denyOverdraft.Checked Then
e.CancelTransaction = True
End If
errorMessage.Text = $"You had an overdraft protection transfer of {e.AmountOverdrafted:C2}"
errorMessage.Visible = True
End SubTim Corey concluye el tutorial resumiendo los puntos clave y las mejores prácticas para trabajar con eventos en C#.
Remover Event Listeners:
customer.CheckingAccount.OverdraftEvent -= CheckingAccount_OverdraftEvent;RemoveHandler customer.CheckingAccount.OverdraftEvent, AddressOf CheckingAccount_OverdraftEventUtilizar EventArgs herencia:
Configuradores privados para propiedades de sólo lectura:
Sintaxis del manejador de eventos:
Operador de condición nula:
El completo tutorial de Tim Corey sobre eventos de C# proporciona información valiosa y ejemplos prácticos para crear, manejar y gestionar eventos de forma eficaz. Siguiendo estas buenas prácticas, los desarrolladores pueden crear aplicaciones más interactivas y con mayor capacidad de respuesta.
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