Home  >  Article  >  Backend Development  >  C# delegate, introduction to event understanding

C# delegate, introduction to event understanding

黄舟
黄舟Original
2016-12-21 14:54:051000browse

Table of contents

l Introduction

l What is delegation

l Understanding of events

l Event keywords

l Finally



Introduction

In the process of learning delegates and events in C#, I read a lot Article to understand what they are and how to use them. Now I will describe the entire understanding process below. Every aspect I learned is probably what you need to master:-).

What is delegation?

The two concepts of delegation and events are completely compatible. A delegate is just a function pointer, that is, it can refer to a function, through the mechanism of passing the address. A delegate is a class that, when you instantiate it, provides a reference function as a parameter to its constructor.

Each delegate has its own signature, for example: Delegate int SomeDelegate(string s, bool b); is a delegate declaration. The signature mentioned here means that the delegate SomeDelegate has formal parameters of string and bool types. , returns an int type.

Mentioned above: When you instantiate a delegate, provide a reference function as a parameter to its constructor. Note here: the function being referenced must have the same signature as the delegate.

Look at the following function:

PRivate int SomeFunction(string str, bool bln){...}

You can pass this function to the constructor of SomeDelegate since they have similar signatures (in other Words, they All have the same parameter type and number, and return the same data type).

SomeDelegate sd = new SomeDelegate(SomeFunction);

sd refers to SomeFunction, that is to say, SomeFunction has been registered by sd. If you call sd, the function SomeFunction will also be called. Remember: I said SomeFunction The meaning of , we will use it later.

Now, you should know how to use delegates, let us continue to understand the event journey...

Understanding of events

We know that in C#:

l Button is a class, when we click When it does, a click event is triggered.

l The clock (Timer) is also a class. Every millisecond, a tick event is triggered.


Let us learn through an example, assuming there is such a plot:

Now there is a Counter class, which has a method CountTo(int countTo, int reachableNum), which means: within the specified time period ( 0~~countTo), when the specified time point reachableNum is reached, a NumberReached event is triggered.

It also has an event: NumberReached, which is a delegate type variable. Meaning: If you name an event, declare it with the event keyword and the delegate type to be used, as shown below:

public event NumberReachedEventHandler NumberReached;



In the above declaration, NumberReachedEventHandle is just a delegate. A more accurate representation should be: NumberReachedDelegate. But Microsoft never thinks of MouseDelegate or PaintDelegate this way, but the title: MouseEventHandler or PaintEventHandler. So

NumberReachedEventHandler sounds more convenient than NumberReachedDelegate, OK? Okay, let's continue, now you know, before we declare the event, we need to define the delegate in the following form:

public delegate void NumberReachedEventHandler(object sender, NumberReachedEventArgs e);

Now declare the delegate NumberReachedEventHandle, which has a void return value and two formal parameters of object and NumberReachedEventArgs. As we emphasized in Section 1, when instantiating a delegate, the function passed as an argument must also have the same signature as the delegate.

In your code, have you used PaintEventArgs or MouseEventArgs to determine the movement position of the mouse? Have you used the Graphics property on the object that triggered the Paint event? In fact, the classes that provide data for users all inherit from the System.EventArgs class, which is what we often call the event parameter class. If the event does not provide parameters, this class will not be defined. In our case, we provide the expected time point through the following class.

public class NumberReachedEventArgs : EventArgs

{

private int _reached;

public NumberReachedEventArgs(int num)

{

this._reached = num;

}

public int ReachedNumber

{

get

return _reached;

                                                                                                                                Take a look inside the Counter class:

namespace Events

{

  public delegate void NumberReachedEventHandler(object sender,

                                               .

​ /// Summary description for Counter. " public Counter()​​​​

//

} u Public Void Countto (Int Countto, Int Reachablenum) {

IF (Counto & LT; Reachablenum)

Throw New ArgumentedException (

Reachab Lenum should be less than countto ");
               for (int ctr=0;ctr<=countTo;ctr++)                                                                        

                       NumberReachedEventArgs                                                       e); Return; //d'T to Count Any More

}}}}









)

{{{ NumberReached(this, e);//Raise the event

}

}

}

}

In Counter, if the specified time point is reached, an event is triggered. There are the following aspects to pay attention to:

l Complete a trigger event by calling NumberReached (which is an instance of the NumberReachedEventHandler delegate).

NumberReached(this, e); In this way, all registered functions can be called.

l Provide event data for all registered functions through NumberReachedEventArgs e = new NumberReachedEventArgs(reachableNum);

l After reading the above code, you may want to ask: Why do we directly use the OnNumberReached(NumberReachedEventArgs e) method to call NumberReached(this, e) instead of the following code?

if(ctr == reachableNum)

{

NumberReachedEventArgs e = new NumberReachedEventArgs(reachableNum);

//OnNumberReached(e);

if(NumberReached != null )

                                                                         e);//Raise the event

}

return;//don't count any more

}

This is a good question, so let us take another look at the OnNumberReached signature:

protected virtual void OnNumberReached(NumberReachedEventArgs e)

① You also understand that the keyword protected restricts that only classes that inherit from this class can call all methods in this class.

②The keyword virtual indicates that this method can be overridden in inherited classes.

These two points are very useful. Suppose you are writing a class that inherits from Counter. By overriding the OnNumberReached method, you can perform other work before the event is triggered.



protected override void OnNumberReached(NumberReachedEventArgs e)

{

  //Do additional work

base.OnNumberReached(e);

}

Note: If you do not call base.On NumberReached(e), then This event is never triggered! This is useful when you inherit from a class and want to exclude some of its other events.

l It should also be noted that the delegate NumberReachedEventHandler is defined outside the class definition, within the namespace, and is visible to all classes.

Okay, it’s time for us to actually use the Counter class.



In our simple application, we have two text boxes, namely: txtCountTo and txtReachable:




The following is the click event of btnRun:

private void btnRun_Click(object sender, System.EventArgs e)

                                                                                                                                                    vert.ToInt32(txtCountTo.Text), Convert.ToInt32(txtReachable .Text)); eachedNumber.ToString());

}



The syntax for initializing event handling is as follows:

oCounter = new Counter();

              oCounter.NumberReached += new NumberReachedEventHandler(oCounter_NumberReached); , only initialize the NumberReachedEventHandler delegate type object (just like you instantiate other objects), notice that the signature of the oCounter_NumberReached method is similar to what I mentioned earlier.

Also note that we use += instead of =; this is because a delegate is a special object that can refer to multiple objects (here it means that it can refer to multiple functions). For example if there is another function oCounter_NumberReached2 with the same signature as oCounter_NumberReached, both functions can be referenced:



oCounter = new Counter();

oCounter.NumberReached += new NumberReachedEventHandler(oCounter _NumberReached) ;

oCounter.NumberReached += new NumberReachedEventHandler(oCounter_NumberReached2);

Now, after an event is triggered, the above two functions are called in sequence.



Depending on the situation, if you want oCounter_NumberReached2 to no longer be called after the NumberReached event occurs, you can simply write like this: oCounter.NumberReached -= new NumberReachedEventHandler(oCounter_NumberReached2);



Finally Let’s take a look Complete source code for reference:


Form1.cs


using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System .Data;

namespace Events
{
  /**////

 
    /// Summary description for Form1. 
    ///
 
    public class Form1 : System.Windows.Forms.Form 
    { 
        Counter oCounter = null; 

        private System.Windows.Forms.Button cmdRun; 
        private System.Windows.Forms.TextBox txtReachable; 
        private System.Windows.Forms.TextBox txtCountTo; 
        private System.Windows.Forms.Label label1; 
        private System.Windows.Forms.Label label2; 
        private System.Windows.Forms.Button btnRemoveDelegate; 
        /**////
                /// Required designer variable. container components = null;

public Form1()
izeComponent();​​​​​​​​​
                        oCounter = new Counter();                                                             use using using using ‐ ‐ oCounter.NumberReached += new ‐NumberReachedEventHandler(oCounter_NumberReached); 2); / Clean up any resources being used.
                                                                                                                                                                                                                                                                               through );        } 

        Windows Form Designer generated code#region Windows Form Designer generated code 
        /**////  
        /// Required method for Designer support - do not modify 
        /// the contents of this method with the 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 = "Reach this number"; 
            //  
            // 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 = "Remove second handler"; 
            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 

        /**////  
        /// The main entry point for the application. 
        ///
 
        [STAThread] 
        static void Main()  
        { 
            Application.Run(new Form1()); 
        } 

        private void btnRun_Click(object sender, System.EventArgs e) 
        { 
            if(txtCountTo.Text == "" || txtReachable.Text=="") 
                return; 
            oCounter.CountTo(Convert.ToInt32(txtCountTo.Text), Convert.ToInt32(txtReachable.Text)); 
        } 

        private void oCounter_NumberReached(object sender, NumberReachedEventArgs e) 
        { 
            MessageBox.Show("Reached: " + e.ReachedNumber.ToString()); 
        } 
        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(oCounter_NumberReached2); 
            oCounter.CountTo(Convert.ToInt32(txtCountTo.Text), Convert.ToInt32(txtReachable.Text)); 
        } 
    } 

  






Counter.cs 


  

using System; 

namespace Events 

    public delegate void NumberReachedEventHandler(object sender, NumberReachedEventArgs e); 

    /**////  
    /// Summary description for Counter. 
    ///
 
    public class Counter 
    { 
        public event NumberReachedEventHandler NumberReached; 
         
        public Counter() 
        { 
            // 
            // TODO: Add constructor logic here 
            // 
        } 
        public void CountTo(int countTo, int reachableNum) 
        { 
            if(countTo < reachableNum) 
                throw new ArgumentException("reachableNum should be less than countTo"); 
            for(int ctr=0;ctr<=countTo;ctr++) 
            { 
                if(ctr == reachableNum) 
                { 
                    NumberReachedEventArgs e = new NumberReachedEventArgs(reachableNum); 
                    OnNumberReached(e); 
                    return;//don't count any more 
                } 
            } 
        } 

        protected virtual void 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 
            { 
                return _reached; 
            } 
        } 
    } 

 以上就是C#委托,事件理解入门的内容,更多相关内容请关注PHP中文网(www.php.cn)! 


Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn