Heim > Artikel > Backend-Entwicklung > C#-Delegierter, Einführung in das Ereignisverständnis
Inhalt
l Einleitung
l Was ist Delegation
l Verständnis von Ereignissen
l Ereignisschlüsselwörter
l Abschließend
Einführung
Während ich Delegierte und Ereignisse in C# lerne, lese ich viele Artikel, um zu verstehen, was sie sind und wie man sie verwendet Der gesamte Verständnisprozess unten ist wahrscheinlich das, was Sie beherrschen müssen :-).
Was ist Delegation?
Die beiden Konzepte Delegation und Events sind völlig kompatibel. Ein Delegate ist einfach ein Funktionszeiger, das heißt, er kann durch Übergabe der Adresse auf eine Funktion verweisen. Ein Delegat ist eine Klasse, die ihrem Konstruktor beim Instanziieren eine Referenzfunktion als Parameter bereitstellt.
Jeder Delegate hat seine eigene Signatur, zum Beispiel: Delegate int SomeDelegate(string s, bool b); ist eine Delegate-Deklaration, die bedeutet, dass der Delegate einen String und einen Bool-Typ-Parameter zurückgibt int-Typ.
Oben erwähnt: Wenn Sie einen Delegaten instanziieren, stellen Sie eine Referenzfunktion als Parameter für seinen Konstruktor bereit. Beachten Sie hier: Die referenzierte Funktion muss dieselbe Signatur wie der Delegat haben.
Sehen Sie sich die folgende Funktion an:
PRivate int SomeFunction(string str, bool bln){...}
Sie können diese Funktion an den Konstruktor von SomeDelegate übergeben, Weil sie ähnliche Signaturen haben (mit anderen Worten, sie haben denselben Parametertyp und dieselbe Parameternummer und geben denselben Datentyp zurück).
SomeDelegate sd = new SomeDelegate(SomeFunction);
sd bezieht sich auf SomeFunction, das heißt, SomeFunction wurde von sd registriert, auch die Funktion SomeFunction wird aufgerufen . Denken Sie daran: Was ich mit SomeFunction meine, werden wir später verwenden.
Jetzt sollten Sie wissen, wie man Delegaten verwendet. Lassen Sie uns die Ereignisreise weiter verstehen...
Verstehen von Ereignissen
Das wissen wir in C#:
l Eine Schaltfläche (Button) ist eine Klasse. Wenn wir darauf klicken, wird ein Klickereignis ausgelöst.
l Die Uhr (Timer) ist ebenfalls eine Klasse. Jede Millisekunde wird ein Tick-Ereignis ausgelöst.
Lassen Sie uns anhand eines Beispiels lernen, vorausgesetzt, es gibt eine Handlung wie diese:
Jetzt gibt es eine Counter-Klasse, die eine Methode CountTo(int countTo, int discoverableNum) hat, Welche Methodendarstellung: Wenn „reachableNum“ innerhalb des angegebenen Zeitraums (0~~countTo) den angegebenen Zeitpunkt erreicht, wird ein NumberReached-Ereignis ausgelöst.
Es gibt auch ein Ereignis: NumberReached, eine Variable vom Typ Delegat. Bedeutung: Wenn Sie ein Ereignis benennen, deklarieren Sie es mit dem Ereignisschlüsselwort und dem zu verwendenden Delegatentyp, wie unten gezeigt:
public event NumberReachedEventHandler NumberReached; In der obigen Anweisung ist NumberReachedEventHandle nur ein Delegat, und eine genauere Darstellung sollte sein: NumberReachedDelegate. Aber Microsoft denkt nie so an MouseDelegate oder PaintDelegate, sondern an den Titel: MouseEventHandler oder PaintEventHandler. Also
NumberReachedEventHandler klingt praktischer als NumberReachedDelegate, OK? OK, fahren wir fort, jetzt wissen Sie, bevor wir das Ereignis deklarieren, müssen wir den Delegaten in der folgenden Form definieren:
öffentlicher Delegat void NumberReachedEventHandler(object sender, NumberReachedEventArgs e);
Der deklarierte Delegat NumberReachedEventHandle hat jetzt einen void-Rückgabewert und zwei formale Parameter von object und NumberReachedEventArgs. Wie wir in Abschnitt 1 betont haben, muss beim Instanziieren eines Delegaten die als Argument übergebene Funktion auch dieselbe Signatur wie der Delegat haben.
Haben Sie in Ihrem Code PaintEventArgs oder MouseEventArgs verwendet, um die Bewegungsposition der Maus zu bestimmen? Haben Sie die Graphics-Eigenschaft für das Objekt verwendet, das das Paint-Ereignis ausgelöst hat? Tatsächlich erben alle Klassen, die Daten für Benutzer bereitstellen, von der Klasse System.EventArgs, die wir häufig als Ereignisparameterklasse bezeichnen. Wenn das Ereignis keine Parameter bereitstellt, wird diese Klasse nicht definiert. In unserem Fall stellen wir den erwarteten Zeitpunkt durch die folgende Klasse bereit.
public class NumberReachedEventArgs : EventArgs
{
private int _reached;
public NumberReachedEventArgs(int num)
{
this._reached = num;
}
public int ReachedNumber
{
get
{ 🎜> return _ erreicht 🎜 >namespace Events
{
public Delegate void NumberReachedEventHandler(object sender,
NumberReachedEventArgs e);
// / < ;summary>
/// Zusammenfassende Beschreibung für Counter
/// öffentliche Klasse Counter
> öffentliches Ereignis NumberReachedEventHandler NumberReached;
public Counter()
//
// TODO: Konstruktorlogik hier hinzufügen
🎜> if( countTo
"); ctr=0;ctr<=countTon++ )
NumberReachedEventArgs e = new NumberReachedEventArgs(
🎜>
OnNumberReached(e);
return; // zählen Sie nicht mehr
}
Geschützte virtuelle void onnumberReached (numberReachEdEventArgs e)
{
if(NumberReached != null)
NumberReached(this, e);//Erhöhen Sie das Ereignis.
Um ein Ereignis auszulösen, müssen folgende Aspekte beachtet werden:
l Schließen Sie ein Triggerereignis ab, indem Sie NumberReached aufrufen (eine Instanz des NumberReachedEventHandler-Delegaten).
NumberReached(this, e); Auf diese Weise können alle registrierten Funktionen aufgerufen werden.
l Bereitstellung von Ereignisdaten für alle registrierten Funktionen über NumberReachedEventArgs e = new NumberReachedEventArgs(reachableNum);
l Nachdem Sie den obigen Code gelesen haben, möchten Sie vielleicht fragen: Warum verwenden wir direkt die Methode OnNumberReached(NumberReachedEventArgs e), um NumberReached(this, e) anstelle des folgenden Codes aufzurufen?
if(ctr == erreichbarNum)
{
NumberReachedEventArgs e = new NumberReachedEventArgs(reachableNum);
//OnNumberReached(e); >
if(NumberReached != null)
{
NumberReached(this, e);//Das Ereignis auslösen
}
return ;//zähle nicht mehr
}
Diese Frage ist gut, also schauen wir uns noch einmal die OnNumberReached-Signatur an:
protected virtual void OnNumberReached ( NumberReachedEventArgs e)
① Sie verstehen auch, dass das Schlüsselwort protected einschränkt, dass nur Klassen, die von dieser Klasse erben, alle Methoden in dieser Klasse aufrufen können.
②Das Schlüsselwort virtual gibt an, dass diese Methode in geerbten Klassen überschrieben werden kann.
Diese beiden Punkte sind sehr nützlich. Angenommen, Sie schreiben eine Klasse, die von Counter erbt. Durch Überschreiben der OnNumberReached-Methode können Sie andere Arbeiten ausführen, bevor das Ereignis ausgelöst wird.
protected override void OnNumberReached(NumberReachedEventArgs e)
{
//Zusätzliche Arbeit ausführen
base.OnNumberReached(e) ;
}
Hinweis: Wenn Sie base.OnNumberReached(e) nicht aufrufen, wird dieses Ereignis nie ausgelöst! Dies ist nützlich, wenn Sie von einer Klasse erben und einige ihrer anderen Ereignisse ausschließen möchten.
l Es ist außerdem zu beachten, dass der Delegat NumberReachedEventHandler außerhalb der Klassendefinition, innerhalb des Namespace, definiert ist und für alle Klassen sichtbar ist.
Okay, es ist Zeit für uns, die Counter-Klasse tatsächlich zu verwenden.
In unserer einfachen Anwendung haben wir zwei Textfelder, nämlich: txtCountTo und txtReachable:
Darunter ist das Klickereignis von btnRun:
private void btnRun_Click(object sender, System.EventArgs e)
Text=="")
return;
oCountTo (Convert.ToInt32(txtCountTo.Text), Convert.ToInt32(txtReachable.Text));
}
Private void OCOUNTER_NUMBERREACHED (Object SENDER, NumberReacheDeventargs E)
{
MESSAGEBOX.show ("Reached:" + E " + E .Reachednumber.tstring ( ); NumberReached += new NumberReachedEventHandler(oCounter_NumberReached); Beachten Sie, dass die Signatur der oCounter_NumberReached-Methode dem ähnelt, was Ich habe es bereits erwähnt.
Beachten Sie auch, dass wir += anstelle von = verwenden. Dies liegt daran, dass ein Delegat ein spezielles Objekt ist, das auf mehrere Objekte verweisen kann (hier bedeutet es, dass es auf mehrere Funktionen verweisen kann). Wenn es beispielsweise eine andere
-Funktion oCounter_NumberReached2 mit derselben Signatur wie oCounter_NumberReached gibt, kann auf beide Funktionen verwiesen werden:
oCounter = new Counter();
oCounter.NumberReached += new NumberReachedEventHandler(oCounter_NumberReached);oCounter.NumberReached += new NumberReachedEventHandler(oCounter_NumberReached2);
Nachdem nun ein Ereignis ausgelöst wurde, werden die beiden oben genannten Funktionen nacheinander aufgerufen.
Wenn Sie möchten, dass oCounter_NumberReached2 nach Eintreten des NumberReached-Ereignisses nicht mehr aufgerufen wird, können Sie je nach Situation einfach so schreiben: oCounter.NumberReached -= new NumberReachedEventHandler(oCounter_NumberReached2);
Lassen Sie uns abschließend einen Blick auf den vollständigen Quellcode als Referenz werfen:
Form1.cs
using System;
mit System.Drawing;
mit System.ComponentModel;
mit System.Data;
{
Containerkomponenten = null;
public Form1
{
🎜> InitializeComponent();
oCounter.NumberReached += new NumberReachedEventHandler(oCounter_NumberReached );
oCounter.NumberReached += new NumberReachedEventHandler(oCounter_NumberReached2); // ( entsorgen )
{
if (components != null)
components.Dispose(); }
Von Windows Form Designer generierter Code#region Von Windows Form Designer generierter Code
/**////
/// Erforderliche Methode für Designer-Unterstützung – nicht ändern.
/// Der Inhalt dieser Methode mit dem Code-Editor.
///
private void InitializeComponent()
{
this.cmdRun = new System.Windows.Forms.Button();
this.txtReachable = new System.Windows.Forms.TextBox();
this.txtCountTo = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.btnRemoveDelegate = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// cmdRun
//
this.cmdRun.Location = new System.Drawing.Point(16, 72);
this.cmdRun.Name = "cmdRun";
this.cmdRun.Size = new System.Drawing.Size(48, 23);
this.cmdRun.TabIndex = 2;
this.cmdRun.Text = "Run";
this.cmdRun.Click += new System.EventHandler(this.cmdRun_Click);
//
// txtReachable
//
this.txtReachable.Location = new System.Drawing.Point(144, 40);
this.txtReachable.Name = "txtReachable";
this.txtReachable.Size = new System.Drawing.Size(56, 20);
this.txtReachable.TabIndex = 1;
this.txtReachable.Text = "";
//
// txtCountTo
//
this.txtCountTo.Location = new System.Drawing.Point(144, 16);
this.txtCountTo.Name = "txtCountTo";
this.txtCountTo.Size = new System.Drawing.Size(56, 20);
this.txtCountTo.TabIndex = 0;
this.txtCountTo.Text = "";
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(16, 16);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(51, 13);
this.label1.TabIndex = 3;
this.label1.Text = "Count To";
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(16, 40);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(99, 13);
this.label2.TabIndex = 4;
this.label2.Text = „Diese Zahl erreichen“;
//
// btnremedelegate
//
this.BTnremedelegate.location = new System.Drawing.Point (16, 104);
this.btnRemoveDelegate.Name = "btnRemoveDelegate";
this.btnRemoveDelegate.Size = new System.Drawing.Size(168, 23);
this.btnRemoveDelegate.TabIndex = 5;
this.btnRemoveDelegate.Text = "Zweiten Handler entfernen";
this.btnRemoveDelegate.Click += new System.EventHandler(this.btnRemoveDelegate_Click);
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(224, 134);
this.Controls.AddRange(new System.Windows.Forms.Control[] {
this.btnRemoveDelegate,
this.label2,
this.label1,
this.txtCountTo,
this.txtReachable,
this.cmdRun});
this.Name = "Form1";
this.Text = "Events";
this.ResumeLayout(false);
}
#endregion
/**////
/// Der Haupteinstiegspunkt für die Anwendung.
///
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
private void btnRun_Click(object sender, System.EventArgs e)
{
if(txtCountTo.Text == "" || txtReachable.Text==" ")
zurück;
oCounter.CountTo(Convert.ToInt32(txtCountTo.Text), Convert.ToInt32(txtReachable.Text));
}
private void oCounter_NumberReached(object sender, NumberReachedEventArgs e)
{
MessageBox.Show("Reached: " +. e.ReachedNumber.To String());
}
private void oCounter_NumberReached2(object sender, NumberReachedEventArgs e)
{
MessageBox.Show("Reached2: " + e.ReachedNumber.ToString() );
}
private void btnRemoveDelegate_Click(object sender, System.EventArgs e)
{
oCounter.NumberReached -= new. NumberReachedEventHandler(oCount er_NumberReached2);
oCounter.CountTo(Convert.ToInt32(txtCountTo.Text), Convert.ToInt32(txtReachable.Text));
}
}
}
Counter.cs
System verwenden;
Namespace-Ereignisse
{
öffentlicher Delegat void NumberReachedEventHandler(object sender, NumberReachedEventArgs e);
/**////
/// Zusammenfassende Beschreibung für Counter.
///
public class Counter
{
public event NumberReachedEventHandler NumberReached;
public Counter()
{
// 🎜> }
public void CountTo(int countTo, int erreichbareNum)
{
if(countTo < erreichbare Zahl)
throw new ArgumentException("reachableNum sollte kleiner als countTo sein");
for(int ctr=0;ctr<=countTo;ctr++)
🎜> NumberReachedEventArgs e = new NumberReachedEventArgs(reachableNum);
OnNumberReached(e);
retour;//nicht mehr zählen
}
}
OnNumberReached(NumberReachedEventArgs e)
{
if(NumberReached! =null)
{
NumberReached(this, e);
}
}
}
public class NumberReachedEventArgs : EventArgs
{
private int _reached;
public NumberReachedEventArgs(int num)
{
this._reached = num;
}
public int ReachedNumber
{
get
ched;
}
}
}
}
以上就是C#委托,事件理解入门的内容,更多相关内容请关注PHP中文网(www.php.cn)!