Contenu
l Introduction
l Qu'est-ce que la délégation
l Compréhension des événements
l Mots-clés de l'événement
l Enfin
Introduction
Dans le processus d'apprentissage des délégués et des événements en C#, j'ai lu de nombreux articles pour comprendre ce qu'ils sont et comment les utiliser. l'ensemble du processus de compréhension ci-dessous. Chaque aspect que j'ai appris est probablement ce que vous devez maîtriser :-).
Qu'est-ce que la délégation ?
Les deux notions de délégation et d'événement sont totalement compatibles. Un délégué est simplement un pointeur de fonction, c'est-à-dire qu'il peut faire référence à une fonction en passant l'adresse. Un délégué est une classe qui, lorsque vous l'instanciez, fournit une fonction de référence en tant que paramètre à son constructeur.
Chaque délégué a sa propre signature, par exemple : Delegate int SomeDelegate(string s, bool b); la signature mentionnée ici signifie que le délégué SomeDelegate a un paramètre string et bool Type, renvoie un. type int.
Mentionné ci-dessus : lorsque vous instanciez un délégué, fournissez une fonction de référence en tant que paramètre à son constructeur. Notez ici : la fonction référencée doit avoir la même signature que le délégué.
Regardez la fonction suivante :
PRivate int SomeFunction(string str, bool bln){...}
Vous pouvez passer cette fonction au constructeur de SomeDelegate, Parce qu'ils ont des signatures similaires (en d'autres termes, ils ont le même type et numéro de paramètre et renvoient le même type de données).
SomeDelegate sd = new SomeDelegate(SomeFunction);
sd fait référence à SomeFunction, c'est-à-dire que SomeFunction a été enregistré par sd. Si vous appelez sd, la fonction SomeFunction sera également appelée. . , rappelez-vous : ce que j’entends par SomeFunction, nous l’utiliserons plus tard.
Maintenant, vous devez savoir utiliser les délégués, continuons à comprendre le parcours événementiel...
Compréhension des événements
On sait ça en C# :
l Button est une classe Lorsque nous cliquons dessus, un événement de clic est déclenché.
l L'horloge (Timer) est aussi une classe Chaque milliseconde, un événement tick est déclenché.
Apprenons à travers un exemple, en supposant qu'il existe un tracé comme celui-ci :
Il existe maintenant une classe Counter, qui a une méthode CountTo(int countTo, int reachableNum), which Méthode de représentation : dans la période de temps spécifiée (0~~countTo), lorsque le point temporel spécifié reachableNum est atteint, un événement NumberReached est déclenché.
Il possède également un événement : NumberReached, qui est une variable de type délégué. Signification : Si vous nommez un événement, déclarez-le avec le mot-clé event et le type de délégué à utiliser, comme indiqué ci-dessous :
public event NumberReachedEventHandler NumberReached ; l'instruction ci-dessus, NumberReachedEventHandle n'est qu'un délégué, et une représentation plus précise devrait être : NumberReachedDelegate. Mais Microsoft ne pense jamais à MouseDelegate ou PaintDelegate de cette façon, mais au titre : MouseEventHandler ou PaintEventHandler. Alors
NumberReachedEventHandler semble plus pratique que NumberReachedDelegate, OK ? OK, continuons, maintenant vous savez, avant de déclarer l'événement, nous devons définir le délégué sous la forme suivante :
délégué public void NumberReachedEventHandler(object sender, NumberReachedEventArgs e);
Le délégué NumberReachedEventHandle déclaré a désormais une valeur de retour void et deux paramètres formels d'objet et NumberReachedEventArgs. Comme nous l'avons souligné dans la section 1, lors de l'instanciation d'un délégué, la fonction passée en argument doit également avoir la même signature que le délégué.
Dans votre code, avez-vous utilisé PaintEventArgs ou MouseEventArgs pour déterminer la position de mouvement de la souris ? Avez-vous utilisé la propriété Graphics sur l'objet qui a déclenché l'événement Paint ? En fait, les classes qui fournissent des données aux utilisateurs héritent toutes de la classe System.EventArgs, que l'on appelle souvent la classe des paramètres d'événement. Si l'événement ne fournit pas de paramètres, cette classe ne sera pas définie. Dans notre cas, nous fournissons le moment attendu via la classe suivante.
classe publique NumberReachedEventArgs : EventArgs
{
private int _reached;
public NumberReachedEventArgs(int num)
{
this._reached = num;
}
public int ReachedNumber
{
obtenir
{ 🎜> return _ atteint; >Événements d'espace de noms
{
délégué public void NumberReachedEventHandler (expéditeur d'objet,
NumberReachedEventArgs e
// / <); ;summary>
/// Description récapitulative du compteur
///
compteur de classe publique
{ >
événement public NumberReachedEventHandler NumberReached;
public Counter()
//
// À FAIRE : Ajouter la logique du constructeur ici
🎜> if( countTo < reachableNum) "reachableNum devrait être inférieur à countTo"); "reachableNum devrait être inférieur à countTo"); "reachableNum devrait être inférieur à countTo"); "); ctr=0;ctr<=countTo;ctr )
NumberReachedEventArgs e = new NumberReachedEventArgs(
🎜>
OnNumberReached(e);
return; //ne compte plus
}
vide virtuel protégé OnNumberReached(NumberReachedEventArgs e)
{
if(NumberReached != null)
NumberReached(this, e);//Soulever l'événement
Pour déclencher un événement, les aspects suivants doivent être pris en compte :
l Complétez un événement déclencheur en appelant NumberReached (qui est une instance du délégué NumberReachedEventHandler).
NumberReached(this, e); De cette façon, toutes les fonctions enregistrées peuvent être appelées.
l Fournir des données d'événement pour toutes les fonctions enregistrées via NumberReachedEventArgs e = new NumberReachedEventArgs(reachableNum);
l Après avoir lu le code ci-dessus, vous voudrez peut-être demander : Pourquoi utilisons-nous directement la méthode OnNumberReached(NumberReachedEventArgs e) pour appeler NumberReached(this, e) au lieu du code suivant ?
if(ctr == reachableNum)
{
NumberReachedEventArgs e = new NumberReachedEventArgs(reachableNum);
//OnNumberReached(e); >
if(NumberReached != null)
{
NumberReached(this, e);//Soulever l'événement
}
return ;//ne compte plus
}
Cette question est bonne, alors revenons sur la signature OnNumberReached :
vide virtuel protégé OnNumberReached ( NumberReachedEventArgs e)
① Vous comprenez également que le mot clé protected restreint que seules les classes qui héritent de cette classe peuvent appeler toutes les méthodes de cette classe.
②Le mot-clé virtual indique que cette méthode peut être remplacée dans les classes héritées.
Ces deux points sont très utiles. Supposons que vous écriviez une classe qui hérite de Counter En remplaçant la méthode OnNumberReached, vous pouvez effectuer d'autres travaux avant que l'événement ne soit déclenché.
protected override void OnNumberReached(NumberReachedEventArgs e)
{
//Effectuer un travail supplémentaire
base.OnNumberReached(e) ;
}
Remarque : Si vous n'appelez pas base.OnNumberReached(e), cet événement ne sera jamais déclenché ! Ceci est utile lorsque vous héritez d'une classe et souhaitez exclure certains de ses autres événements.
l Il convient également de noter que le délégué NumberReachedEventHandler est défini en dehors de la définition de la classe, au sein de l'espace de noms, et est visible par toutes les classes.
D'accord, il est temps pour nous d'utiliser réellement la classe Counter.
Dans notre application simple, nous avons deux zones de texte, à savoir : txtCountTo et txtReachable :
Ci-dessous c'est l'événement clic de btnRun :
private void btnRun_Click(object sender, System.EventArgs e)
Text=="")
return
oCounter.CountTo (Convert.ToInt32(txtCountTo.Text), Convert.ToInt32(txtReachable.Text));
}
<<>
Vide privé OCOUNTER_NUMBERREACHED (Object SENDER, NumberReacheDeventargs E)
ACHEDNUMBER.TOSTRING () ; = new NumberReachedEventHandler(oCounter_NumberReached); La signature de la méthode oCounter_NumberReached est similaire à ce que j'ai mentionné plus tôt.
Notez également que nous utilisons = au lieu de = ; c'est parce qu'un délégué est un objet spécial qui peut faire référence à plusieurs objets (ici, cela signifie qu'il peut faire référence à plusieurs fonctions). Par exemple, s'il existe une autre fonction
oCounter_NumberReached2 avec la même signature que oCounter_NumberReached, les deux fonctions peuvent être référencées :
oCounter = new Counter(
<); 🎜> oCounter.NumberReached = new NumberReachedEventHandler(oCounter_NumberReached
);oCounter.NumberReached = new NumberReachedEventHandler(oCounter_NumberReached2);
Maintenant, après le déclenchement d'un événement, les deux fonctions ci-dessus sont appelées dans l'ordre.
Selon la situation, si vous souhaitez que oCounter_NumberReached2 ne soit plus appelé après l'événement NumberReached, vous pouvez simplement écrire comme ceci : oCounter.NumberReached -= new NumberReachedEventHandler(oCounter_NumberReached2);
Enfin, jetons un coup d'œil au code source complet pour référence :
Form1.cs
en utilisant System ;
en utilisant System.Drawing;
en utilisant System.Collections;
en utilisant System.ComponentModel;
en utilisant System.Windows.Forms
en utilisant System.Data;
{
Composants du conteneur = null;
public Form1()
{
🎜> InitializeComponent();
oCounter.NumberReached = new NumberReachedEventHandler(oCounter_NumberReached) ;
oCounter.NumberReached = new NumberReachedEventHandler(oCounter_NumberReached2);
/// protected override void Dispose( bool disposing )
if( disposing ) (components != null)
Éliminer(); }
Code généré par le Concepteur de formulaires Windows#region Code généré par le Concepteur de formulaires Windows
/**////
/// Méthode requise pour le support de Designer - ne modifiez pas
/// le contenu de cette méthode avec l'éditeur de code.
///
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 = "Exécuter";
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 = "Atteindre ce numéro";
//
// btnRemoveDelegate
//
this.btnRemoveDelegate.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 = "Supprimer le deuxième gestionnaire";
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.txtAccessible,
this.cmdRun} );
this.Name = "Form1";
this.Text = "Événements";
this.ResumeLayout(false);
}
#endregion
/**////
/// Le point d'entrée principal de l'application.
///
[STAThread]
static void Main()
{
Application.Run(new Form1());
retour ;
oCounter.CountTo(Convert.ToInt32(txtCountTo.Text), Convert.ToInt32(txtReachable.Text));
}
private void oCounter_NumberReached(objet expéditeur, NumberReachedEventArgs e)
{
MessageBox.Show("Atteint : " Chaîne());
}
private void oCounter_NumberReached2(objet expéditeur, NumberReachedEventArgs e)
{
MessageBox.Show("Reached2: " e.ReachedNumber.ToString() );
}
private void btnRemoveDelegate_Click (expéditeur de l'objet, System.EventArgs e)
{
oCounter.NumberReached -= new NumberReachedEventHandler(oCount er_NumberReached2);
oCounter.CountTo(Convert.ToInt32(txtCountTo.Text), Convert.ToInt32(txtReachable.Text));
}
}
}
Counter.cs
en utilisant le système ;
Événements d'espace de noms
{
délégué public void NumberReachedEventHandler (expéditeur d'objet, NumberReachedEventArgs e);
/**////
/// Description récapitulative du compteur.
///
compteur de classe publique
{
événement public NumberReachedEventHandler NumberReached ;
}
public void CountTo(int countTo, int reachableNum)
{
if(countTo < reachableNum)
lancer une nouvelle ArgumentException ("reachableNum doit être inférieur à countTo");
for(int ctr=0;ctr<=countTo;ctr )
{
if(ctr == reachableNum)
{ NumberReachedEventArgs e = new NumberReachedEventArgs(reachableNum);
OnNumberReached(e);
retour;//ne compte plus
}
}
}
vide virtuel protégé OnN umberReached(NumberReachedEventArgs e)
{
if(NumberReached! =null)
{
Nombre atteint (this, e);
}
}
}
public class NumberReachedEventArgs : EventArgs
{
private int _reached;
public NumberReachedEventArgs(int num)
{
this._reached = num;
}
public int attedNumber
{
get
{
return _reached;
}
}
}
}
以上就是C#委托,事件理解入门的内容,更多Application PHP (www.php.cn)