This article has been included in the "C # Illustrated Tutorial" Reading Notes directory sticker, click to access the directory for more content.
First, commissioned a glimpse: An object that owns the method
(1) Essence: An object that holds one or more methods; a delegate differs from a typical object in that the execution of a delegate actually executes the method it "holds". If you understand a delegate from the perspective of C + +, you can interpret it as a type-safe, object-oriented function pointer .
(2) How to use a delegate?
① declaring delegate type (delegate keyword)
② declaring a delegate variable using the delegate type
③ Adding a method to a delegate type
④ Invoke Delegate Execution method
(3) The constancy of the entrustment:
The combination delegate, the delegate = = Increment method, and the delegate-to-= Removal method Let us look like the delegates were modified, but they were not modified. In fact, the delegate is constant .
What actually happens when you increment and remove a method for a delegate is to create a new delegate whose invocation list is the result of the addition and removal of the method.
(4) Examples of Delegates:
① simple with parameter commissioning demo
delegate void Mydel (int value); Declares the delegate type class program { void printlow (int value) { Console.WriteLine ("{0}-Lowvalue", value); } void Printhigh (int value) { Console.WriteLine ("{0}-Highvalue", value); } static void Main (string[] args) {program Program = new Program (); Mydel Mydel; Declares a delegate type //Gets a random number between the 0~99 randomly random = new Random (); int randomvalue = random. Next (in); Create a delegate object that contains a concrete method and assign it to the Mydel variable mydel = Randomvalue <? New Mydel (program. Printlow): New Mydel (program. Printhigh); Execution of delegated Mydel (randomvalue); Console.readkey (); } }
② Simple no parameter multi-method list delegate Demo
delegate void Printfunction (); class test{public void Print1 () { Console.WriteLine ("Print1-instance"); } public static void Print2 () { Console.WriteLine ("Print2-Static");} } Class program{ static void Main () { Test t = new Test (); Printfunction PF; PF = t.print1; PF + = Test.print2; PF + = T.print1; PF + = Test.print2; if (PF! = null) { pf (); } else { Console.WriteLine ("Delegate is Empty"); } }}
③ Demo with return value
delegate int Mydel (); Class myclass{ int intvalue = 5; public int Add2 () { intvalue + = 2; return intvalue; } public int Add3 () { Intvalue + = 3; return intvalue;} } Class program{ static void Main () { MyClass mc = new MyClass (); Mydel Mdel = MC. ADD2; Mdel + = MC. ADD3; Mdel + = MC. ADD2; Console.WriteLine ("Value: {0}", Mdel ());} }
Ii. Anonymous method: I'm sorry.
In a method held by a delegate, if a method is used only once, in which case it is not necessary to create a separate named method in addition to the need to create the delegate syntax. As a result, anonymous methods emerged.
An anonymous method is a method that inline (inline) declares when the delegate is initialized .
Here's a look at the two-version code: is the anonymous method much more concise than the anonymous method?
① named parameter
View Code
② Anonymous Parameters
View code Three, lambda expression: delicious grammatical sugar
(1) Essence: "Grammatical sugar" which simplifies grammar;
Lambda Source: From 1920 to 1930, mathematicians Alonzo Church and others invented lambda integrals. Lambda integrals are a set of systems for representing functions that use the Greek letter lambda (λ) to represent nameless functions. In recent years, functional programming languages (such as Lisp) use this term to represent expressions that can directly describe function definitions, which no longer need to have a name.
(2) Key points:
The list of parameters in the ①LAMBDA expression (number of parameters, type and location) must match the delegate;
A parameter list in a ② expression does not necessarily need to contain a type unless the delegate has a ref or out keyword (the declaration must be displayed at this time);
③ if there are no arguments, a set of empty parentheses must be used;
(3) Syntax:
Iv. a glimpse of the event: Publisher and Subscriber patterns
The Publisher subscriber pattern defines a one-to-many dependency that allows multiple subscriber objects to listen to a Subject object at the same time. When the subject object changes its state, all the subscriber objects are notified so that they can automatically update their state.
A method provided by a subscriber is called a callback method because the publisher executes these methods to "call the Subscriber's method back." They can also be called event handlers because they are code that is called for handling events.
Here's a classic code to look at the application of this pattern:
Using system;delegate void Handler (); Class incrementer{public event Handler Countedadozen; public void Docount () {for (int i=1; i < i++) if (i% = = 0 && Countedadozen! = null)
countedadozen (); }} Class dozens{public int Dozenscount {get; private set;} Public dozens (Incrementer Incrementer) { dozenscount = 0; Incrementer. Countedadozen + = Incrementdozenscount; } void Incrementdozenscount () { dozenscount++; }} Class program{ static void Main () { Incrementer incrementer = new Incrementer (); Dozens Dozenscounter = new dozens (incrementer); Incrementer. Docount (); Console.WriteLine ("Number of dozens = {0}", dozenscounter.dozenscount);} }
V. The whole process of events: Declaration, subscription, and triggering
(1) Declaring the event:
The ① event is declared in a class;
② additional methods need to match the signature and return type of the delegate type;
③ declared as public;
④ cannot be new;
(2) Subscription events:
① Use + = To increase event handlers for events;
② can use anonymous methods and lambda expressions;
(3) Trigger event:
① uses the event name, followed by a list of arguments enclosed in parentheses;
The ② parameter list must match the delegate type of the event;
Six, the road to standard: EventHandler
Asynchronous processing of programs is a great scenario for using C # events. The Windows GUI extensively uses events for the use of events. The NET Framework provides a standard pattern: theEventHandler delegate type.
(1) The first parameter holds a reference to the object that triggered the event (object type, which can match any type of instance);
(2) The second parameter holds the state information (an instance of the EventArgs class), indicating what program is applicable to the application;
(3) The return type is void;
Now let's refactor just the Subscriber class, using the standard EventHandler delegate type:
Class dozens{public int Dozenscount {get; private set;} Public dozens (Incrementer Incrementer) { dozenscount = 0; Incrementer. Countedadozen + = Incrementdozenscount; } void Incrementdozenscount (object source, EventArgs e) { dozenscount++; }}
So, just to see that in order to maintain the standard mode, we can only have two parameters, the first one is the object reference that triggers the event, the second is an instance of the EventArgs class, how to pass the data in the event? The answer must be to find a pointcut on the second argument. We can declare a subclass derived from EventArgs, where we declare the properties of the arguments we want to pass to hold the data we need to be passed in. Tips: The name of this custom subclass is suggested to end with EventArgs.
public class incrementereventargs:eventargs{Public int IterationCount {get; set;}}
Now that you have used a custom class, you must also change the generic delegate and declare the custom class object to use the custom class in the other parts of the event.
Class Incrementer{public event eventhandler<incrementereventargs> Countedadozen; public void Docount () { Incrementereventargs args = new Incrementereventargs (); for (int i=1; i <; i++) if (i% = = 0 && Countedadozen! = null) { args. IterationCount = i; Countedadozen (this, args);}}}
In order to get the data values passed in the executing program, you can directly derive the properties of the custom class from the EventArgs.
Class dozens{public int Dozenscount {get; private set;} Public dozens (Incrementer Incrementer) { dozenscount = 0; Incrementer. Countedadozen + = Incrementdozenscount; } void Incrementdozenscount (object source, Incrementereventargs e) { Console.WriteLine ("incremented at Iteration: {0} in {1} ", E.iterationcount, source. ToString ()); dozenscount++;} }
Mind Map of this chapter
Attachment
Mind Mapping (JPG, PDF, and mmap source files) Download: http://pan.baidu.com/s/1hqA7KH2
Zhou Xurong
Source: http://www.cnblogs.com/edisonchou/
The copyright of this article is owned by the author and the blog Park, welcome reprint, but without the consent of the author must retain this paragraph, and in the article page obvious location to give the original link.
"C # Illustrated Tutorial" Five reading Notes: Delegates and events