C# Event verstehen
Ereignisse in C# sind ein grundlegendes Konzept, das viele Entwickler verwenden, aber möglicherweise nicht vollständig verstehen, insbesondere wenn es darum geht, eigene Ereignisse zu erstellen. Tim Corey bietet in seinem Video "C# Events - Creating and Consuming Events in Your Application" eine umfassende Anleitung zum Erstellen und Verwenden von Ereignissen und geht dabei auf bewährte Verfahren und erweiterte Funktionen ein.
In diesem Artikel werden wir uns mit C#-Ereignissen befassen, wobei wir uns auf ihre Syntax konzentrieren, wie sie definiert sind und wie sie bei der Lösung gängiger Programmierprobleme helfen. Das Verständnis der Ereignisbehandlung in C# ist für die Erstellung von reaktionsschnellen Anwendungen unerlässlich, und dieser Artikel wird Ihnen helfen, die Kernkonzepte der benutzerdefinierten Fehlerprotokollierung, der Ausnahmebehandlung und der ereignisgesteuerten Programmierung zu verstehen.
Einführung in Ereignisse
In C# und anderen Programmiersprachen spielen Ereignisse eine entscheidende Rolle bei der ereignisgesteuerten Programmierung, die es Anwendungen ermöglicht, auf Aktionen wie Benutzerinteraktionen oder Systemänderungen zu reagieren. Im Vergleich zu anderen Programmiersprachen bietet C# einen strukturierten Ansatz für den Umgang mit Ereignissen und ist damit ideal für schnelle und kleine Anwendungen. Ereignisse in C# werden durch bestimmte Aktionen ausgelöst, und diese Aktionen rufen entsprechende Event-Handler auf, um die gewünschten Aufgaben auszuführen.
Tim beginnt mit der Erklärung, dass die meisten Entwickler mit Ereignissen in C# vertraut sind, aber nicht wissen, wie man benutzerdefinierte Ereignisse erstellt. Ziel des Videos ist es, Ereignisse vorzustellen, die Erstellung von benutzerdefinierten Ereignissen zu erläutern, ihre Funktionen zu diskutieren und bewährte Verfahren zu beschreiben.
Demo Anwendung Walk-through
Tim verwendet eine einfache Bankanwendung, die mit Windows Forms (WinForms) erstellt wurde, um Ereignisse zu demonstrieren. Die Anwendung simuliert grundlegende Bankgeschäfte für einen Kunden, einschließlich der Anzeige von Salden und der Erfassung von Transaktionen.
-
Anwendungsübersicht:
- Die Anwendung hat zwei Formulare: eines zur Anzeige von Kontoständen und Transaktionen und ein weiteres zum Erfassen neuer Transaktionen.
- Sie enthält Schaltflächen zur Simulation von Kreditkartenkäufen und zur Handhabung von Überziehungen durch Überweisung von Spar- auf Giroguthaben.
-
Hauptformular:
- Zeigt den Namen des Kunden sowie den Kontostand des Giro- und Sparkontos an.
- Zeigt Listen von Transaktionen für beide Konten.
- Enthält eine Schaltfläche zum Öffnen des Transaktionserfassungsformulars.
-
Transaktionsformular:
- Ermöglicht es dem Benutzer, Transaktionsbeträge einzugeben.
- Simuliert das Tätigen von Einkäufen und den Umgang mit Überziehungen, indem Geld vom Spar- auf das Girokonto übertragen wird.
Code hinter der Demo-App
Tim erklärt den Backend-Code der Demo-Bankanwendung:
-
Kundenklasse:
- Stellt einen Kunden mit Eigenschaften für den Kundennamen und zwei Konten (Giro- und Sparkonto) dar.
- Die Klasse Customer ist einfach, dient aber als guter Ausgangspunkt für das Verständnis der Verwaltung mehrerer Konten.
-
Kontenklasse:
- Verwaltet die Details eines Bankkontos, einschließlich Kontoname, Saldo und Transaktionsliste.
- Die Eigenschaft Balance ist vom Typ Dezimal für präzise monetäre Berechnungen.
- Die Eigenschaft "Transaktionen" ist eine schreibgeschützte Liste, um externe Änderungen zu verhindern.
-
Handhabung von Einzahlungen und Zahlungen:
- AddDeposit Methode: Fügt dem Konto eine Einzahlung hinzu, aktualisiert den Saldo und protokolliert die Transaktion.
- MakePayment-Methode: Bearbeitet Abhebungen, einschließlich der Überprüfung, ob genügend Geld vorhanden ist, und der Verwaltung des Überziehungsschutzes, indem bei Bedarf Geld von einem Ersatzkonto übertragen wird.
-
Überziehungsschutz:
- Die Anwendung enthält eine Logik zur Handhabung von Überziehungen. Wenn der Saldo des Girokontos für eine Transaktion nicht ausreicht, prüft die Anwendung das Sparkonto, um den Fehlbetrag zu decken. Wenn der kombinierte Saldo ausreicht, wird der erforderliche Betrag auf das Girokonto überwiesen und die Transaktion abgeschlossen.
Code-Beispiele finden Sie direkt im Video von Tim Corey, wo er den Code von 3:18 bis 18:27 erklärt.
Ereignis: Button Click
In diesem Abschnitt taucht Tim Corey in die Funktionsweise von Schaltflächenklickereignissen in Windows Forms ein und erklärt, wie diese Ereignisse verdrahtet sind und wie sie funktionieren.
Klickereignisse auf Schaltflächen verstehen
Tim beginnt mit der Erläuterung des bekannten Konzepts der Schaltflächenklick-Ereignisse in Windows Forms-Anwendungen. Wenn Sie im Designer auf eine Schaltfläche doppelklicken, generiert Visual Studio automatisch eine Ereignisbehandlungsmethode für das Klickereignis.
-
Ereignishandler-Methode:
- Diese Methode wird immer dann aufgerufen, wenn die Schaltfläche angeklickt wird. Hier platzieren Sie den Code, der als Reaktion auf den Klick auf die Schaltfläche ausgeführt werden soll.
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 } -
Verkabelung der Veranstaltung:
- Die Ereignisbehandlungsmethode ist mit dem Schaltflächenklick-Ereignis in der Formulardesignerdatei (FormName.Designer.cs) verdrahtet. Dies geschieht mit dem Operator +=, um den Event-Handler zum Klick-Ereignis der Schaltfläche hinzuzufügen.
this.recordTransactionButton.Click += new System.EventHandler(this.recordTransactionButton_Click);this.recordTransactionButton.Click += new System.EventHandler(this.recordTransactionButton_Click);
Erstellen und Aufrufen von benutzerdefinierten Ereignissen
Tim erklärt, wie man benutzerdefinierte Ereignisse in C# erstellt, beginnend mit der Klasse Account, in der die Ereignisse ausgelöst werden.
-
Definieren eines Ereignisses:
- Ein Ereignis wird mit dem Schlüsselwort event definiert. Sie sieht ähnlich aus wie eine öffentliche Variable, ist aber speziell für Ereignisse gedacht.
public event EventHandler<string> RaiseTransactionApprovedEvent;public event EventHandler<string> RaiseTransactionApprovedEvent; -
Auslösung des Ereignisses:
- Ereignisse werden mit der Invoke-Methode ausgelöst, normalerweise innerhalb der Klasse, die das Ereignis definiert. Die Invoke-Methode nimmt zwei Parameter: den Sender (in der Regel
this) und Ereignisdaten (in diesem Fall ein String).
private void OnTransactionApproved(string transactionName) { RaiseTransactionApprovedEvent?.Invoke(this, transactionName); }private void OnTransactionApproved(string transactionName) { RaiseTransactionApprovedEvent?.Invoke(this, transactionName); } - Ereignisse werden mit der Invoke-Methode ausgelöst, normalerweise innerhalb der Klasse, die das Ereignis definiert. Die Invoke-Methode nimmt zwei Parameter: den Sender (in der Regel
-
Verkabelung und Handhabung von Ereignissen:
- Abonnieren Sie das Ereignis mit dem Operator += und definieren Sie eine Methode zur Behandlung des Ereignisses, wenn es ausgelöst wird.
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 }
Verwendung von Ereignissen zur Aktualisierung der Benutzeroberfläche
Tim erklärt, wie man Ereignisse verwendet, um die Browser-Benutzeroberfläche automatisch zu aktualisieren, wenn bestimmte Aktionen stattfinden, z. B. wenn eine Transaktion genehmigt wird.
-
Eröffnung von Veranstaltungen:
- Lösen Sie das benutzerdefinierte Ereignis aus, nachdem eine Transaktion genehmigt wurde.
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); } -
Abonnieren von Ereignissen in der Benutzeroberfläche:
- Abonnieren Sie das Ereignis im Hauptformular, um die Transaktionsliste zu aktualisieren, sobald eine neue Transaktion genehmigt wird.
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 }
Event?.Invoke() Erklärt
Tim Corey erklärt die Verwendung der Syntax ?.Invoke() beim Auslösen von Ereignissen in C#. Dieser moderne Ansatz vereinfacht den Code und gewährleistet die Thread-Sicherheit.
Der Fragezeichen-Operator
Das Fragezeichen (?.) vor Invoke ist ein Null-Bedingungsoperator. Es wird geprüft, ob der Event-Handler null ist, bevor er aufgerufen wird, um mögliche Ausnahmen zu vermeiden.
-
Traditionelle Herangehensweise:
- Bisher mussten Entwickler mehrere Codezeilen verwenden, um zu prüfen, ob der Event-Handler null ist, und ihn dann aufrufen.
if (RaiseTransactionApprovedEvent != null) { RaiseTransactionApprovedEvent(this, depositName); }if (RaiseTransactionApprovedEvent != null) { RaiseTransactionApprovedEvent(this, depositName); } -
Moderne Herangehensweise mit ?.Invoke():
- Der Null-Conditional-Operator rationalisiert diesen Prozess, indem er die Null-Prüfung durchführt und das Ereignis in einer Zeile aufruft.
RaiseTransactionApprovedEvent?.Invoke(this, depositName);RaiseTransactionApprovedEvent?.Invoke(this, depositName);- Wenn
RaiseTransactionApprovedEventnull ist, erfolgt die Ausführung nicht, wodurch effektiv jede Ausnahme vermieden wird.
-
Vorteile:
- Vereinfacht Code: Reduziert die Menge an Code, die zum sicheren Aufrufen von Ereignissen benötigt wird.
- Thread Safety: Eliminiert Race Conditions, indem es auf Null prüft und das Ereignis in einem einzigen Schritt aufruft.
Zuhören und Code für die Veranstaltung schreiben
Tim erklärt, wie man auf benutzerdefinierte Ereignisse in einer Windows Forms-Anwendung hört und die Benutzeroberfläche entsprechend aktualisiert.
-
Abonnement für Veranstaltungen:
- Abonnieren Sie das benutzerdefinierte Ereignis mit dem Operator +=.
customer.CheckingAccount.TransactionApprovedEvent += CheckingAccount_TransactionApprovedEvent;customer.CheckingAccount.TransactionApprovedEvent += CheckingAccount_TransactionApprovedEvent; -
Ereignishandler-Methode:
- Definieren Sie eine Methode zur Behandlung des Ereignisses. Mit dieser Methode wird die Benutzeroberfläche auf der Grundlage der Ereignisdaten aktualisiert.
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"); }
Erstellung des benutzerdefinierten Ereignisses: Ereignis in Aktion und Rekapitulation
Tim demonstriert den gesamten Prozess des Erstellens, Auslösens und Behandelns benutzerdefinierter Ereignisse in Aktion.
-
Auslösung des Ereignisses:
- Lösen Sie das Ereignis aus, nachdem eine Transaktion genehmigt wurde oder wenn sich der Saldo ändert.
private void OnTransactionApproved(string transactionName) { RaiseTransactionApprovedEvent?.Invoke(this, transactionName); }private void OnTransactionApproved(string transactionName) { RaiseTransactionApprovedEvent?.Invoke(this, transactionName); } -
Behandlung mehrerer Ereignisse:
- Stellen Sie sicher, dass die Anwendung auf mehrere Ereignisse wie Transaktionen und Kontostandsänderungen reagiert, damit die Benutzeroberfläche in Echtzeit aktualisiert werden kann.
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"); } -
Ausführen der Anwendung:
- Tim führt die Anwendung aus, um zu demonstrieren, wie die Benutzeroberfläche auf der Grundlage von durch Transaktionen ausgelösten Ereignissen automatisch aktualisiert wird.
Informationen zu Ereignisargumenten: Fehlersuche
Tim zeigt, wie man Ereignisse debuggt und die mit ihnen gesendeten Informationen untersucht.
-
Setzen eines Haltepunkts:
- Setzen Sie einen Haltepunkt in der Event-Handler-Methode, um die Ereignisdaten zu untersuchen.
private void CheckingAccount_TransactionApprovedEvent(object sender, string e) { // Breakpoint here }private void CheckingAccount_TransactionApprovedEvent(object sender, string e) { // Breakpoint here } -
Debugging :
- Führen Sie die Anwendung aus und führen Sie eine Transaktion durch, um das Ereignis auszulösen. Überprüfen Sie die Ereignisargumente im Debugger.
- Der Parameter sender gibt die Instanz an, die das Ereignis ausgelöst hat, und der Parameter e enthält die Ereignisdaten.
Ein weiteres benutzerdefiniertes Ereignis erstellen (Überziehungsereignis)
Tim Corey erweitert die Demo durch die Erstellung eines weiteren benutzerdefinierten Ereignisses zur Behandlung von Überziehungssituationen. Dieses Ereignis wird ausgelöst, wenn es zu einer Überziehung kommt und informiert den Benutzer über den Überziehungsbetrag.
Definieren des Überziehungsereignisses
Tim beginnt mit der Definition eines neuen Ereignisses in der Klasse Account für Überziehungsszenarien:
-
Ereigniserklärung:
- Definieren Sie das Ereignis mit dem Schlüsselwort event und einem Dezimaltyp, um den Überziehungsbetrag zu übergeben.
public event EventHandler<decimal> OverdraftEvent;public event EventHandler<decimal> OverdraftEvent; -
Auslösung des Ereignisses:
- Das Ereignis wird in dem Teil des Codes ausgelöst, in dem eine Überziehung erfolgreich stattfindet.
if (overdraftSuccessful) { OverdraftEvent?.Invoke(this, overdraftAmount); }if (overdraftSuccessful) { OverdraftEvent?.Invoke(this, overdraftAmount); }
Abonnieren des Überziehungsereignisses auf der Dashboard-Seite
-
Verkabelung der Veranstaltung:
- Abonnieren Sie das Ereignis "Überziehung" im Dashboard-Formular.
customer.CheckingAccount.OverdraftEvent += CheckingAccount_OverdraftEvent;customer.CheckingAccount.OverdraftEvent += CheckingAccount_OverdraftEvent; -
Umgang mit dem Ereignis :
- Definieren Sie einen Event-Handler, um eine Nachricht anzuzeigen, wenn eine Überziehung auftritt.
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; } -
Auslösen und Anzeigen des Ereignisses:
- Wenn eine Überziehung auftritt, wird das Ereignis ausgelöst und die Benutzeroberfläche aktualisiert, um den Benutzer zu benachrichtigen.
You had an overdraft protection transfer of $20.44
An mehreren Stellen auf das Ereignis achten
Tim erklärt, wie man dasselbe Ereignis in mehreren Sprachen und Formen anhören kann, um die Vielseitigkeit von Ereignissen zu demonstrieren.
-
Ein Etikett zu einem anderen Formular hinzufügen:
- Hinzufügen eines Etiketts zu einem sekundären Formular zur Anzeige von Überziehungsmeldungen.
<asp:Label ID="errorMessage" runat="server" Visible="false" /><asp:Label ID="errorMessage" runat="server" Visible="false" />HTML -
Abonnement für die Veranstaltung:
- Abonnieren Sie das Überziehungsereignis im sekundären Formular.
customer.CheckingAccount.OverdraftEvent += SecondaryForm_OverdraftEvent;customer.CheckingAccount.OverdraftEvent += SecondaryForm_OverdraftEvent; -
Umgang mit dem Ereignis :
- Definieren Sie einen Event-Handler, um die Überziehungsmeldung auf dem sekundären Formular anzuzeigen.
private void SecondaryForm_OverdraftEvent(object sender, decimal e) { errorMessage.Visible = true; }private void SecondaryForm_OverdraftEvent(object sender, decimal e) { errorMessage.Visible = true; } -
Simultane Ereignisbehandlung:
- Tim zeigt, dass das Ereignis in mehreren Formen gleichzeitig behandelt werden kann, um sicherzustellen, dass alle relevanten Teile der Anwendung angemessen auf das Ereignis reagieren.
Both the main form and the secondary form display the overdraft message when the event is triggered.
Ereignis-Listener aus dem Speicher entfernen
Tim hebt hervor, wie wichtig es ist, Ereignislisten zu bereinigen, um Speicherlecks zu vermeiden und eine gute Anwendungsleistung zu gewährleisten.
-
Abmeldung von Veranstaltungen:
- Es ist wichtig, sich von Ereignissen abzumelden, bevor eine Klasseninstanz zerstört oder ein Formular geschlossen wird.
customer.CheckingAccount.OverdraftEvent -= CheckingAccount_OverdraftEvent;customer.CheckingAccount.OverdraftEvent -= CheckingAccount_OverdraftEvent;Warum es wichtig ist:
- Werden Ereignisse nicht abbestellt, kann dies zu Speicherlecks führen, da die Objekte, die auf Ereignisse warten, möglicherweise nicht ordnungsgemäß gelöscht werden.
-
Verwendung von benannten Methoden:
- Vermeiden Sie die Verwendung anonymer Funktionen für Event-Handler, da dies die Abmeldung von den Events erschwert.
// Good practice: using named methods for event handlers// Good practice: using named methods for event handlers
Generic EventHandler: Übergabe einer Klasse für T
Tim Corey erklärt die besten Praktiken für die Übergabe von Daten durch Ereignisse, insbesondere die Vorteile der Verwendung einer Klasse anstelle von einfachen Datentypen wie String oder Decimal.
Warum eine Klasse für Ereignisdaten verwenden
Tim beginnt mit der Frage, warum die Verwendung einfacher Datentypen für Ereignisse weniger üblich ist und warum es normalerweise besser ist, eine Klasse zu übergeben:
-
Flexibilität und Skalierbarkeit:
- Mit einer Klasse können Sie mehrere zusammenhängende Daten über ein Ereignis übergeben. Wenn Sie später weitere Daten hinzufügen müssen, können Sie die Klasse einfach erweitern, ohne die Ereignissignatur zu ändern.
-
EventArgs-Vererbung:
- Während es früher erforderlich war, dass jedes Objekt, das durch ein Ereignis übergeben wird, von EventArgs erben musste, ist dies heute nicht mehr der Fall. Die Vererbung von EventArgs kann jedoch für Konsistenz und Klarheit von Vorteil sein.
Erstellen der Klasse Overdraft EventArgs
Tim demonstriert, wie man eine benutzerdefinierte EventArgs-Klasse für das Überziehungsereignis erstellt.
-
Bestimmen Sie die Klasse:
- Erstellen Sie eine neue Klasse, die von EventArgs erbt und Eigenschaften für die Daten enthält, die Sie über das Ereignis übergeben möchten.
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; } } -
Verwendung der Klasse in der Veranstaltung:
- Aktualisieren Sie die Ereignisdeklaration, um die benutzerdefinierte EventArgs-Klasse zu verwenden.
public event EventHandler<OverdraftEventArgs> OverdraftEvent;public event EventHandler<OverdraftEventArgs> OverdraftEvent; -
Auslösung des Ereignisses:
- Übergeben Sie beim Aufrufen des Ereignisses eine Instanz der benutzerdefinierten EventArgs-Klasse.
OverdraftEvent?.Invoke(this, new OverdraftEventArgs(amountNeeded, "Additional info"));OverdraftEvent?.Invoke(this, new OverdraftEventArgs(amountNeeded, "Additional info"));
Bedeutung von schreibgeschützten Eigenschaften
Tim betont, wie wichtig es ist, schreibgeschützte Eigenschaften in der EventArgs-Klasse zu verwenden, um eine versehentliche Änderung von Ereignisdaten zu verhindern.
-
Änderungen vermeiden:
- Wenn Eigenschaften in der EventArgs-Klasse öffentliche Setter haben, kann jeder Event-Handler die Daten ändern, was zu unerwartetem Verhalten führen kann.
- Durch die Verwendung privater Setter und die Initialisierung von Eigenschaften über den Konstruktor wird sichergestellt, dass die Ereignisdaten konsistent bleiben.
-
Beispiel für das Problem:
- Tim demonstriert, wie sich die Änderung von Ereignisdaten in einem Ereignis-Handler auf andere Handler auswirken kann, wenn die Eigenschaften nicht schreibgeschützt sind.
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 } -
Lösung:
- Verwenden Sie private Setter und übergeben Sie Daten über den Konstruktor, um Eigenschaften schreibgeschützt zu machen.
public decimal AmountOverdrafted { get; private set; } public string MoreInfo { get; private set; }public decimal AmountOverdrafted { get; private set; } public string MoreInfo { get; private set; }
Ausnahme bei Verwendung von Public Set (59:29)
Tim Corey weist auf eine wichtige Ausnahme von der Regel hin, private Setter für Ereignisdateneigenschaften zu verwenden. Diese Ausnahme ist dann gegeben, wenn Sie es den Zuhörern von Ereignissen erlauben müssen, die Ereignisdaten zu ändern, z. B. in Fällen, in denen eine Transaktion aufgrund bestimmter Bedingungen abgebrochen werden kann.
Beispiel: Abbrechen einer Transaktion
Tim gibt ein Beispiel, bei dem ein Event-Handler eine Transaktion abbrechen muss. Dies wird durch Hinzufügen einer CancelTransaction-Eigenschaft zur benutzerdefinierten EventArgs-Klasse erreicht.
-
Definieren der Eigenschaft:
- Fügen Sie der Klasse EventArgs eine öffentliche Eigenschaft mit einem Getter und Setter hinzu.
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; } } -
Eigenschaft im Event Handler einstellen:
- Im Dashboard kann der Event-Handler diese Eigenschaft setzen, um die Transaktion abzubrechen.
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; } -
Prüfen der Eigenschaft in der Quellmethode:
- Prüfen Sie in der Methode, die das Ereignis auslöst, ob die Eigenschaft CancelTransaction auf true gesetzt ist, bevor Sie fortfahren.
if (args.CancelTransaction) { return false; // Transaction is canceled }if (args.CancelTransaction) { return false; // Transaction is canceled }
Die Anwendung interaktiver gestalten
Tim verfeinert die Anwendung weiter, um sie interaktiver und benutzerfreundlicher zu gestalten.
-
Hinzufügen eines Kontrollkästchens für die Überziehungskontrolle:
- Fügen Sie ein Kontrollkästchen in das Formular ein, mit dem der Benutzer den Überziehungsschutz aktivieren oder deaktivieren kann.
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); } -
Handhabung des Checkbox-Status:
- Aktualisieren Sie im Event-Handler für das Kontrollkästchen die Logik, um den Zustand des Kontrollkästchens bei der Entscheidung über den Abbruch einer Transaktion zu berücksichtigen.
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 } } -
Aktualisierung des Event Handlers:
- Stellen Sie sicher, dass der Event-Handler den Status des Kontrollkästchens respektiert, um Überziehungen zuzulassen oder zu verweigern.
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; }
Zusammenfassung
Tim Corey fasst zum Abschluss des Tutorials die wichtigsten Punkte und bewährten Verfahren für die Arbeit mit Ereignissen in C# zusammen.
-
Ereignis-Listener entfernen:
- Entfernen Sie Ereignis-Listener immer vor dem Zerstören von Objekten, um Speicherlecks zu vermeiden.
- Verwenden Sie den Operator -=, um sich von Ereignissen abzumelden.
customer.CheckingAccount.OverdraftEvent -= CheckingAccount_OverdraftEvent;customer.CheckingAccount.OverdraftEvent -= CheckingAccount_OverdraftEvent; -
Verwendung EventArgs Vererbung:
- Auch wenn es nicht zwingend erforderlich ist, kann die Vererbung von EventArgs für die Konsistenz und die Verwendung integrierter Funktionen wie EventArgs.Empty von Vorteil sein.
-
Private Setter für schreibgeschützte Eigenschaften:
- Verwenden Sie private Setter, um unbeabsichtigte Änderungen an Ereignisdaten zu verhindern. Erlauben Sie öffentliche Setter nur, wenn es notwendig ist, wie z. B. bei stornierbaren Transaktionen.
- Syntax für Ereignisbehandler :
- Verwenden Sie das EventHandler-Delegat, um Ereignisse zu definieren und ein klares, konsistentes Muster für die Übergabe von Ereignisdaten bereitzustellen.
-
Null-Bedingungs-Operator:
- Verwenden Sie den Null-Bedingungs-Operator (?.Invoke()), um Ereignisse sicher aufzurufen, ohne Null-Referenz-Ausnahmen zu riskieren.
Abschluss
Tim Coreys umfassendes Tutorial zu C#-Ereignissen bietet wertvolle Einblicke und praktische Beispiele für die Erstellung, Handhabung und Verwaltung von Ereignissen. Durch die Befolgung dieser Best Practices können Entwickler interaktivere und reaktionsschnellere Anwendungen erstellen.
