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
Zdarzenia w C# są fundamentalnym pojęciem, które wielu programistów wykorzystuje, ale nie zawsze w pełni rozumie, zwłaszcza gdy chodzi o tworzenie własnych zdarzeń. Tim Corey przedstawia kompleksowy przewodnik dotyczący tworzenia i używania zdarzeń, omawiając najlepsze praktyki i zaawansowane funkcje w swoim wideo "C# Events - Creating and Consuming Events in Your Application".
W tym artykułe zamierzamy zgłębić zdarzenia w C#, koncentrując się na ich składni, jak są definiowane i jak pomagają rozwiązywać typowe problemy programistyczne korzystając z przykładów wideo Tima Coreya. Zrozumienie obsługi zdarzeń w C# jest niezbędne do budowania responsywnych aplikacji, a ten artykuł pomoże Ci uchwycić kluczowe pojęcia dotyczące niestandardowego logowania błędów, obsługi wyjątków i programowania zdarzeniowego.
W C# i językach programowania zdarzenia odgrywają kluczową rolę w programowaniu zdarzeniowym, umożliwiając aplikacjom reagowanie na działania, takie jak interakcje użytkowników lub zmiany systemowe. W porównaniu do innych języków programowania, C# oferuje strukturalne podejście do obsługi zdarzeń, co czyni go idealnym zarówno dla szybkich, jak i małych aplikacji. Zdarzenia w C# są wywoływane przez określone akcje, a te akcje wywołują odpowiednie obsługujące zdarzenia do wykonania pożądanych zadań.
Tim zaczyna wyjaśniając, że większość programistów zna zdarzenia w C#, ale może nie wiedzieć, jak tworzyć niestandardowe zdarzenia. Celem wideo jest wprowadzenie do zdarzeń, przejście przez tworzenie niestandardowych zdarzeń, omówienie ich funkcji i nakreślenie najlepszych praktyk.
Tim korzysta z prostej aplikacji bankowej zbudowanej w Windows Forms (WinForms) do zademonstrowania zdarzeń. Aplikacja symuluje podstawowe operacje bankowe dla jednego klienta, w tym wyświetlanie sald i rejestrowanie transakcji.
Przegląd aplikacji:
Główny formularz:
Formularz transakcji:
Tim wyjaśnia kod zaplecza aplikacji bankowej demonstracyjnej:
Klasa klienta:
Klasa konta:
Obsługa wpłat i płatności:
Ochrona przed przekroczeniem salda:
Jeśli chodzi o przykłady kodu, możesz od razu obejrzeć film Tima Coreya, w którym wyjaśnia on kod od 3:18 do 18:27.
W tej sekcji Tim Corey zagłębił się w działanie zdarzeń kliknięcia przycisku w Windows Forms, wyjaśniając, w jaki sposób zdarzenia te są połączone i jak funkcjonują.
Tim zaczyna od wyjaśnienia znanej koncepcji zdarzeń kliknięcia przycisku w aplikacjach Windows Forms. Po dwukrotnym kliknięciu przycisku w projektancie program Visual Studio automatycznie generuje metodę obsługi zdarzenia dla zdarzenia kliknięcia.
Metoda obsługi zdarzeń:
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 SubPodłączanie zdarzenia:
this.recordTransactionButton.Click += new System.EventHandler(this.recordTransactionButton_Click);AddHandler Me.recordTransactionButton.Click, AddressOf Me.recordTransactionButton_ClickTim wyjaśnia, jak tworzyć niestandardowe zdarzenia w języku C#, zaczynając od klasy Account, w której będą wyzwalane zdarzenia.
Definiowanie zdarzenia:
public event EventHandler<string> RaiseTransactionApprovedEvent;Public Event RaiseTransactionApprovedEvent As EventHandler(Of String)Wywołanie zdarzenia:
this) i dane zdarzenia (w tym przypadku ciąg znaków).private void OnTransactionApproved(string transactionName)
{
RaiseTransactionApprovedEvent?.Invoke(this, transactionName);
}Private Sub OnTransactionApproved(ByVal transactionName As String)
RaiseTransactionApprovedEvent?.Invoke(Me, transactionName)
End SubPodłączanie i obsługa zdarzeń:
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 wyjaśnia, jak używać zdarzeń do automatycznej aktualizacji interfejsu użytkownika przeglądarki, gdy mają miejsce określone działania, takie jak zatwierdzenie transakcji.
Generowanie zdarzeń:
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 SubSubskrypcja zdarzeń w interfejsie użytkownika:
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 wyjaśnia użycie składni ?.Invoke() podczas generowania zdarzeń w języku C#. To nowoczesne podejście upraszcza kod i zapewnia bezpieczeństwo wątków.
Znak zapytania (?) przed słowem Invoke oznacza operator warunkowy null. Sprawdza, czy procedurka obsługi zdarzenia ma wartość null przed jej wywołaniem, zapobiegając potencjalnym wyjątkom.
Podejście tradycyjne:
if (RaiseTransactionApprovedEvent != null)
{
RaiseTransactionApprovedEvent(this, depositName);
}If RaiseTransactionApprovedEvent IsNot Nothing Then
RaiseTransactionApprovedEvent(Me, depositName)
End IfNowoczesne podejście z ?.Invoke():
RaiseTransactionApprovedEvent?.Invoke(this, depositName);RaiseTransactionApprovedEvent?.Invoke(Me, depositName)RaiseTransactionApprovedEvent jest null, wywołanie nie następuje, skutecznie unikając wyjątków.Zalety:
Tim wyjaśnia, jak nasłuchiwać zdarzeń niestandardowych w aplikacji Windows Forms i odpowiednio aktualizować interfejs użytkownika.
Subskrypcja wydarzeń:
customer.CheckingAccount.TransactionApprovedEvent += CheckingAccount_TransactionApprovedEvent;AddHandler customer.CheckingAccount.TransactionApprovedEvent, AddressOf CheckingAccount_TransactionApprovedEventMetoda obsługi zdarzeń:
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 demonstruje cały proces tworzenia, wywoływania i obsługi zdarzeń niestandardowych w praktyce.
Wywołanie zdarzenia:
private void OnTransactionApproved(string transactionName)
{
RaiseTransactionApprovedEvent?.Invoke(this, transactionName);
}Private Sub OnTransactionApproved(ByVal transactionName As String)
RaiseTransactionApprovedEvent?.Invoke(Me, transactionName)
End SubObsługa wielu zdarzeń:
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 SubUruchamianie aplikacji:
Tim pokazuje, jak debugować zdarzenia i sprawdzać informacje wysyłane wraz z nimi.
Ustawianie punktu przerwania:
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 SubDebugowanie:
Tim Corey rozszerza demo, tworząc kolejne niestandardowe zdarzenie do obsługi sytuacji przekroczenia salda. Zdarzenie to zostanie wywołane w przypadku wystąpienia debetu i powiadomi użytkownika o kwocie debetu.
Tim zaczyna od zdefiniowania nowego zdarzenia w klasie Account dla scenariuszy przekroczenia salda:
Deklaracja zdarzenia:
public event EventHandler<decimal> OverdraftEvent;Public Event OverdraftEvent As EventHandler(Of Decimal)Wywołanie zdarzenia:
if (overdraftSuccessful)
{
OverdraftEvent?.Invoke(this, overdraftAmount);
}If overdraftSuccessful Then
RaiseEvent OverdraftEvent(Me, overdraftAmount)
End IfPodłączanie zdarzenia:
customer.CheckingAccount.OverdraftEvent += CheckingAccount_OverdraftEvent;AddHandler customer.CheckingAccount.OverdraftEvent, AddressOf CheckingAccount_OverdraftEventObsługa zdarzenia:
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 SubWyzwalanie i wyświetlanie zdarzenia:
You had an overdraft protection transfer of $20.44
Tim wyjaśnia, jak nasłuchiwać tego samego zdarzenia w wielu językach i formach, demonstrując wszechstronność zdarzeń.
Dodawanie etykiety do innego formularza:
<asp:Label ID="errorMessage" runat="server" Visible="false" />
Rejestracja na wydarzenie:
customer.CheckingAccount.OverdraftEvent += SecondaryForm_OverdraftEvent;AddHandler customer.CheckingAccount.OverdraftEvent, AddressOf SecondaryForm_OverdraftEventObsługa zdarzenia:
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 SubObsługa zdarzeń równoczesnych:
Both the main form and the secondary form display the overdraft message when the event is triggered.
Tim podkreśla znaczenie czyszczenia detektorów zdarzeń w celu zapobiegania wyciekom pamięci i zapewnienia prawidłowej wydajności aplikacji.
Rezygnacja ze zdarzeń:
customer.CheckingAccount.OverdraftEvent -= CheckingAccount_OverdraftEvent;RemoveHandler customer.CheckingAccount.OverdraftEvent, AddressOf CheckingAccount_OverdraftEventDlaczego to ważne:
Korzystanie z nazwanych metod:
// Good practice: using named methods for event handlers' Good practice: using named methods for event handlersTim Corey wyjaśnia najlepsze praktyki dotyczące przekazywania danych za pośrednictwem zdarzeń, szczególnie zalety używania klasy zamiast prostych typów danych, takich jak string czy decimal.
Tim zaczyna, omawiając, dlaczego używanie prostych typów danych dla zdarzeń jest mniej powszechne i dlaczego lepiej jest zazwyczaj przekazywać klasę:
Elastyczność i skalowalność:
Dziedziczenie EventArgs:
Tim demonstruje, jak stworzyć niestandardową klasę EventArgs dla zdarzenia niedopłaty.
Zdefiniuj klasę:
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 ClassKorzystanie z klasy w zdarzeniu:
public event EventHandler<OverdraftEventArgs> OverdraftEvent;Public Event OverdraftEvent As EventHandler(Of OverdraftEventArgs)Wywołanie zdarzenia:
OverdraftEvent?.Invoke(this, new OverdraftEventArgs(amountNeeded, "Additional info"));OverdraftEvent?.Invoke(Me, New OverdraftEventArgs(amountNeeded, "Additional info"))Tim podkreśla znaczenie używania właściwości tylko do odczytu w klasie EventArgs, aby zapobiec przypadkowej modyfikacji danych zdarzenia.
Unikanie modyfikacji:
Przykład problemu:
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 SubRozwiązanie:
public decimal AmountOverdrafted { get; private set; }
public string MoreInfo { get; private set; }Public Property AmountOverdrafted As Decimal
Public Property MoreInfo As StringTim Corey podkreśla ważny wyjątek od zasady używania prywatnych setterów dla właściwości danych zdarzenia. Ten wyjątek dotyczy sytuacji, gdy konieczne jest umożliwienie słuchaczom zdarzenia modyfikacji danych zdarzenia, na przykład w przypadkach, gdy transakcja może zostać anulowana na podstawie określonych warunków.
Tim przedstawia przykład, w którym obsługujący zdarzenie może potrzebować anulować transakcję. Osiąga się to przez dodanie właściwości CancelTransaction do niestandardowej klasy EventArgs.
Definiowanie właściwości:
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 ClassUstawienie właściwości w obsługującym zdarzenie:
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 SubSprawdzanie właściwości w metodzie źródłowej:
if (args.CancelTransaction)
{
return false; // Transaction is canceled
}If args.CancelTransaction Then
Return False ' Transaction is canceled
End IfTim dalej udoskonala aplikację, aby była bardziej interaktywna i przyjazna dla użytkownika.
Dodanie pola wyboru dla kontroli przekroczenia:
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 SubObsługa stanu pola wyboru:
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 SubAktualizacja obsługującego zdarzenie:
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 podsumowuje tutorial, omawiając kluczowe punkty i najlepsze praktyki dotyczące pracy ze zdarzeniami w C#.
Usuń słuchaczy zdarzeń:
customer.CheckingAccount.OverdraftEvent -= CheckingAccount_OverdraftEvent;RemoveHandler customer.CheckingAccount.OverdraftEvent, AddressOf CheckingAccount_OverdraftEventUżyj dziedziczenia EventArgs :
Prywatne settery dla właściwości tylko do odczytu:
Składnia obsługującego zdarzenie:
Operator warunkowy null:
Kompleksowy tutorial Tima Coreya o zdarzeniach C# zapewnia wartościowe spostrzeżenia i praktyczne przykłady dotyczące tworzenia, obsługi i zarządzania zdarzeniami efektywnie. Podążając za tymi najlepszymi praktykami, programiści mogą tworzyć bardziej interaktywne i responsywne aplikacje.
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