The concept of delegate-related is described in the previous article, where the delegate instance holds one or a set of actions that will be used by the delegate instance at a particular time in the program.
If you have done GUI program development, you may be familiar with the above description. In a GUI program, clicking a button triggers a click event and then performs a series of operations that are stored in a delegate instance.
Next we'll look at the events.
Use a question in a delegate
Back to the example of Apple and Foxconn in the previous article, Apple entrusted Foxconn with the Assembly, packaging and shipping of the iphone.
Based on the above description, we modified the code to add an order attribute to the Apple class, and Apple sent a notification to Foxconn as soon as it received a new order, and Foxconn performed a series of operations (Assembly, packaging, and shipping).
In the main program, Apple delegated the iphone's assembly, packaging, and shipping tasks to Foxconn, and then every time Apple receives an order, it will let Foxconn perform a series of operations by entrusting the example "Verdortoassembleiphone".
classapple{//declaring delegate types Public Delegate voidAssembleiphonehandler (intnum); PublicAssembleiphonehandler Verdortoassembleiphone; Public voidDesigniphone () {Console.WriteLine ("Design Iphone by Apple"); } Private intOrdernum; Public intOrdernum {Get{return This. Ordernum;} Set { This. Ordernum =value; if(Verdortoassembleiphone! =NULL) {Verdortoassembleiphone ( This. Ordernum); } } }}classfoxconn{//the same method as the delegate type signature Public voidAssembleiphone (intnum) {Console.WriteLine ("Assemble {0} Iphone by Foxconn", num); } Public voidPackiphone (intnum) {Console.WriteLine ("Pack {0} Ipnone by Foxconn", num); } Public voidShipiphone (intnum) {Console.WriteLine ("Ship {0} Iphone by Foxconn", num); }}classprogram{Static voidMain (string[] args) {Apple Apple=NewApple (); Foxconn Foxconn=NewFoxconn (); Apple. Verdortoassembleiphone=NewApple.assembleiphonehandler (Foxconn. Assembleiphone); Apple. Verdortoassembleiphone+=NewApple.assembleiphonehandler (Foxconn. Packiphone); Apple. Verdortoassembleiphone+=NewApple.assembleiphonehandler (Foxconn. Shipiphone); Apple. Ordernum= -; Console.read (); }}
Let's look at the problem in this example implementation:
- If the user incorrectly uses "=" instead of "+ =" When establishing a delegate chain, then the delegation chain is broken.
- In the main program, we can bypass the set order step and call the delegate instance "Apple" directly. Verdortoassembleiphone (99); " It's unreasonable to let Foxconn do the work.
classprogram{Static voidMain (string[] args) {Apple Apple=NewApple (); Foxconn Foxconn=NewFoxconn (); //Create a delegate instanceApple. Assembleiphone =NewApple.assembleiphonehandler (Foxconn. Assembleiphone); Apple. Assembleiphone+=NewApple.assembleiphonehandler (Foxconn. Packiphone); Apple. Assembleiphone = new Apple.assembleiphonehandler (Foxconn. Shipiphone); Apple. Designiphone (); //invocation of the delegate instance Apple. Verdortoassembleiphone (© ); Console.read (); }}
The appearance of the event
To solve the above two problems, the concept of events has occurred, and the change we have to make is to add the event keyword when declaring the delegate instance.
Public Event Assembleiphonehandler Verdortoassembleiphone;
At this point, the above two problematic code will be compiled at the time of the error.
The above problem is solved, but what is the event keyword, what is the relationship between events and delegates, and how does "Verdortoassembleiphone" understand?
In-depth understanding of events
In fact, the following statement is still more difficult to understand, the first reaction to see is, what is the relationship between the delegate and the event, the event keyword and the delegate type "Assembleiphonehandler" is what relationship.
Public Event Assembleiphonehandler Verdortoassembleiphone;
in fact, an event can be interpreted as a property of a delegate that restricts access to the delegate instance by encapsulating the delegate instance. Let's take a look at this program through IL and get it.
Let's take a look at the results of IL to analyze what the event really is. Before we start, I'm sure everyone will be familiar with the concept of property, so let's start with the familiar attributes.
The concept of C # properties
First look at what we are familiar with, "Ordernum" is a property of an order quantity that we define, and it has a set of Get/set methods. Using the Get/set method of this property, we can access the "ordernum" field.
Using IL to view the "Ordernum" property, we can see the corresponding Get/set method for this property.
Public int32 Get_ordernum () {} Public void ' value ') { }
Event
Next look at the "Verdortoassembleiphone" event, we understand the event as a property, from the IL, we can see a pair of Addon/removeon methods in the event to manipulate our delegate instance (think of the property's Get/set method).
At the same time, we see that the compiler generated a private field (below), from which we can see that the event "Verdortoassembleiphone" is essentially a variable of a delegate type. Since this variable is private, it also explains why we cannot directly access the variable outside the class that defines the event.
. Field Private class _1_1_delegate.apple/assembleiphonehandler Verdortoassembleiphone
Conversion of event code
Based on the above analysis, we can see that the compiler helped us with the following code conversion. This adds some restrictions to delegate instance access through the event keyword.
C # code for the original Declaration event:
public event Assembleiphonehandler Verdortoassembleiphone;
Compiler-Converted code:
Private Assembleiphonehandler Verdortoassembleiphone; Public void ' value ' {}publicvoid'value') {}
From the above analysis, you can see that the event encapsulates an instance of the delegate type, making:
- Within the class that defines the event, whether you declare it to be public or protected, it is always private, meaning that the event cannot be called outside the class that defines the event
- Outside the class that defines the event, the access qualifier for adding "+ =" and removing the "-=" delegate instance is the same as the accessor used to declare the event
- That is, if the event is declared as private or this protect, then the class that defines the event cannot have "+ =" and "=" Operations on the event
Event programming
In fact, the above example is just a simple demonstration. In many cases, the event is used in conjunction with two parameters: Event source and event arguments.
Therefore, in event programming, you can refer to some of the following specifications:
- Unify named delegate variables in Eventnameeventhandler: EventName is the name of the event
- Delegate accepts two parameters, the name of the parameter is uniformly named sender and E: The first parameter type is object, the second argument is the event argument type, named Eventnameeventargs, and inherits from the System.EventArgs class
- If you do not need to pass any data in the event, you also need to declare two parameters: the first parameter is the default object sender, the second parameter can use the system default System.EventArgs class
Summarize
This article introduces the concept and principle of the event, explains how to encapsulate the delegate instance through the event, and resolves two problems encountered in the delegate example.
Also understand the use of events:
- Declare events with the event keyword,
- < event decorations > event < delegate type > < events name >;
- Event invocation, because the event is essentially a delegate type, the invocation event is the same as invoking the delegate, but the invocation of the event can only occur within the class that defines the event
Understanding C # Events