C # Delegate and event)

Source: Internet
Author: User

In C #, the delegate is a reference type. In other languages, the closest thing to the delegate is the function pointer. However, the delegate not only stores the reference to the method entry point, it also stores references to object instances used to call methods. In short, delegation is a type of secure function pointer.

 

Looking at its concept, it may be very vague. Let's give an example to illustrate it from a simple perspective. (Strong reminder: Pay attention to some key comments in the code. The code can be copied and directly run .)
 

Demand: Charging System billing standard: 1 RMB/hour for members; temporary users: 1.5 RMB/hour.

// Let's first look at how to implement it without using delegation.

Usingsystem; namespace does not use delegate {class program {static void main (string [] ARGs) {charging (3, user. normaluser); Charging (3, user. vipuser) ;}// enumerate public Enum user {vipuser, normaluser} // check public static void charging (INT hour, user) {Switch (User) {Case user. vipuser: vipuser (hour); break; Case user. normaluser: normaluser (hour); break ;}// public static void vipuser (INT hour) {console. writeline ("you are a member, used for {0} hours, you need to pay {1} RMB", hour, 1 * hour);} public static void normaluser (INT hour) {console. writeline ("You are a temporary user, used for {0} hours, you need to pay {1} RMB", hour, 1.5 * hour );}}}

// Running result: You are a temporary user and have been using it for 3 hours. You need to pay 4.5 yuan.

You have been a member for 3 hours and you need to pay 3 RMB

 

// Obviously, although this solves the problem, it is easy to think that the scalability of this solution is very poor. If we need to add other checkout methods in the future, you have to modify the enumeration and charging () methods repeatedly to meet new requirements.

 

// Use a delegate to implement

 

Usingsystem; namespace use delegate {Public Delegate void hour (inthour); Class program {static void main (string [] ARGs) {extends delegate1, delegate2; delegate1 = vipuser; delegate2 = normaluser; charging (3, delegate1); Charging (3, delegate2) // here we mainly want to explain: You can assign multiple methods to the same delegate, or // call it to bind multiple methods to the same delegate. When you call this delegate, the bound methods are called in turn. Delegate1 + = delegate2; Charging (2, delegate1); // Since you can bind a method to a delegate, you should also have a way to unbind the method, this syntax is "-="} public static void charging (INT hour, chargingdelegate charge) {charge (hour);} public static void vipuser (INT hour) {console. writeline ("you are a member, used for {0} hours, you need to pay {1} RMB", hour, 1 * hour);} public static void normaluser (INT hour) {console. writeline ("You are a temporary user, used for {0} hours, you need to pay {1} RMB", hour, 1.5 * hour );}}}

// Running result: You are a Member and have spent 3 hours. You need to pay 3 RMB.

You are an ordinary user and have spent 3 hours. You need to pay 4.5 yuan.

You have been a member for 3 hours and you need to pay 3 RMB

You are an ordinary user and have spent 3 hours. You need to pay 4.5 yuan.

 

// In this way, we can see that the switch statement is blocked by the delegate.

 

Summary: A delegate is a class that defines the type of the method so that the method can be passed as a parameter of another method. This way, the method is dynamically assigned to the parameter, it can avoid using the IF-else (switch) statement in a large number in the program, and make the program more scalable.

 

// Although we have achieved scalability, we can make the following improvements to the above Code to implement object encapsulation in consideration of object-oriented features.

Usingsystem; namespace use delegate {class program {// more concise client static void main (string [] ARGs) {chargingmanager CM = newchargingmanager (); cm. delegate1 = vipuser; cm. delegate1 + = normaluser; cm. charging (3);} // the billing method is public static void vipuser (INT hour) {console. writeline ("you are a member, used for {0} hours, you need to pay {1} RMB", hour, 1 * hour);} public static void normaluser (INT hour) {console. writeline ("You are a temporary user, used for {0} hours, you need to pay {1} RMB", hour, 1.5 * hour) ;}} Public Delegate void chargingdelegate (inthour); // Since delegate type variables can be declared (in the preceding example, delegate1 ), we can encapsulate this variable in the greetmanager class. Class chargingmanager {public chargingdelegate delegate1; Public void charging (INT hour) {If (delegate1! = NULL) delegate1 (hour );}}}

// Running result: You are a Member and have spent 3 hours. You need to pay 3 RMB.

You are an ordinary user and have spent 3 hours. You need to pay 4.5 yuan.

 

 

// There is a very strange statement (publicchargingdelegate delegate1;). Not all fields should be declared as public. The proper method is to make public when public is used, it should be private.

But here, we cannot change it to private, because the purpose of declaring a delegate is to expose it to the class client for method registration. You declare it as private, the client is invisible to it.

I can't help but think about what we would do if delegate1 is not a delegate type but a string or Int type? Naturally, fields are encapsulated using properties.

 

At this time, we have to use the event!

 

Let's optimize the Code:

Usingsystem; namespace use delegate {class program {static void main (string [] ARGs) {chargingmanager CM = newchargingmanager (); // cm. makecharge = vipuser; // "=", which indicates that the value assignment syntax (direct access) reports an error and can only be placed on the right of + = or-=. It indicates that makecharge is declared private. Cm. makecharge + = vipuser; cm. makecharge + = normaluser; cm. charging (3);} // the billing method is public static void vipuser (INT hour) {console. writeline ("you are a member, used for {0} hours, you need to pay {1} RMB", hour, 1 * hour);} public static void normaluser (INT hour) {console. writeline ("You are a temporary user, used for {0} hours, you need to pay {1} RMB", hour, 1.5 * hour );}} public Delegate void chargingdelegate (inthour); Class chargingmanager {// declare the event makecharge, whose type is chargingdelegate Public event chargingdelegate makecharge; // although it is public, there is an additional event. Makecharge becomes private. The client proves public void charging (INT hour) {makecharge (hour );}}}

We can see that in the client, an error is reported when the "=" value assignment syntax (direct access) is used, which can only be placed on the right side of + = or-=. It indicates that makecharge is declared private.

 

Is the event only intended to make a shared object private? Of course not. For details, see the following instance.

 

Requirement: recharge the host card in the charging system. In the database, the balance of the card is changed, and the recharge record is saved.

 

Code implementation:

Usingsystem; namespace delegation and events {class program {static void main (string [] ARGs) {recharge rc = newrecharge ("100"); updatebalance UB = newupdatebalance ("100 "); chargerecord Cr = newchargerecord ("100"); // The updatebalance update method is instantiated by entrusting eventhandler to register to the recharge event makerecharge. RC. makerecharge + = neweventhandler (ub. Update); // instantiate the record method of chargerecord and entrust eventhandler to register it in the makerecharge event. RC. makerecharge + = neweventhandler (Cr. record); RC. charge () ;}}// declare to delegate eventhandler Public Delegate void eventhandler (); // recharge class recharge {private string strmoney; Public recharge (string money) {This. strmoney = money;} // declare the event makerecharge. The event type is to delegate eventhandler public event eventhandler makerecharge; Public void charge () {console. writeline ("Now recharge {0} RMB", strmoney); // when the charge method is executed, if If the event is registered, run makerecharge if (makerecharge! = NULL) {makerecharge () ;}}// change the balance class updatebalance {private string strmoney; Public updatebalance (string money) {This. strmoney = money;} public void Update () {console. writeline ("recharge successful, balance (original balance) + {0} RMB", strmoney) ;}// store the recharge record class chargerecord {private string strmoney; public chargerecord (string money) {This. strmoney = money;} public void record () {console. writeline ("the recharge record is saved successfully. This recharge {0} RMB", strmoney );}}}

Note: here we use an important design pattern: Observer pattern. it can be considered that there is an observer mode first, and only delegated event technology is available. the observer design pattern is to define a one-to-many dependency between objects, so that when the state of an object changes, other objects dependent on it will be automatically notified and updated. It is a loosely coupled design model.

 

In summary, we have studied delegation and events from the shortest to the deep test. Note the following points:

1. delegate is a type of reference method. Once a delegate is assigned a method, the Delegate will have the same behavior. The use of delegate methods can have parameters and return values like any other method. A delegate can be seen as an abstraction of a function and a class of a function. A delegated instance represents a specific function.

2. A delegate can also be considered as a data type that can be used to define a volume. However, it is a special data type and can accept only one function as a value, more specifically, the delegate variable can accept the address of a function.

3. A delegate can carry multiple methods, and all methods are called in sequence. More importantly, it can make the methods carried by the delegate object not necessarily belong to the same class.

4. The methods carried by the delegate object must have the same parameter list and return value type.

 

 

 

 

 

 

 

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.