Introduction
Delegates and events are widely used in the. Net framework, however, a good understanding of delegates and events is not easy for many people who are not in touch with C # for a long time. They are like a sill, the person who passed the threshold, think it is too easy, and not the past people every time to see the Commission and events feel the heart Don't (Biè) panic, mixed body uncomfortable. In this article, I'll go through two examples of what is a delegate, why I use delegates, the origins of events, the meanings of delegates and events in the. Net framework, delegates, and events to the observer design pattern, and also a discussion of their intermediate code.
To use a method as a parameter to a method
Let's take a look at the following two simplest methods, regardless of how the title is wrapped or what the delegate is, and they are simply outputting a word of greeting on the screen:
Public void Greetpeople (string name) { // do some extra things, such as initialization and so on, here slightly Englishgreeting (name);} Public void Englishgreeting (string name) { Console.WriteLine ("" + name);}
Regardless of whether these two methods have any practical significance. Greetpeople used to say hello to someone when we pass the name parameter that represents someone's name, say "Jimmy," and in this method, the Englishgreeting method is called, passing the name parameter again, The englishgreeting is used to output "morning, Jimmy" to the screen.
Now suppose this program needs globalization, oops, no, I am Chinese, I do not understand what "morning" means, how to do it? OK, we'll add a Chinese version of the greeting method:
Public void Chinesegreeting (string name) { Console.WriteLine ("" + name);}
At this time, Greetpeople also need to change a change, otherwise how to determine which version of the greeting greeting method appropriate? Before we do this, we'd better define an enumeration as the basis for judgment:
public enum language{中文版, Chinese} public void Greetpeople (string name, Language Lang) { // do something extra, like initialize and so on, here a little Swith (lang) { case language.english: Englishgreeting (name); break ; case Language.Chinese:ChineseGreeting (name); break ; }}
OK, although this solves the problem, but I do not say it is easy to think that the solution is very poor scalability, if we need to add the Korean version, Japanese version, we have to repeatedly modify the enumeration and Greetpeople () method to adapt to the new requirements.
Before considering a new solution, let's take a look at Greetpeople's method signature:
public void Greetpeople (string name, Language Lang)
We only look at string name, where string is the parameter type, name is a parameter variable, and when we assign the name string "Jimmy" it represents the value of "Jimmy", and when we assign it "Zhang Ziyang" it represents the value of "Zhang Ziyang". We can then perform other operations on the name within the method body. Hey, this is nonsense, just learn the program will know.
If you think about it again, if the Greetpeople () method can accept a parameter variable, this variable can represent another method, and when we assign a value englishgreeting to the variable, it represents the Englsihgreeting () method When we assign a value to Chinesegreeting, it represents the Chinesegreeting () method. We name this parameter variable makegreeting, so it is not possible to assign a value to this makegreeting parameter when calling the Greetpeople () method, as in assigning a value to name ( Chinesegreeting or englsihgreeting, etc.)? We can then use makegreeting in the body of the method, as well as with other parameters. However, since makegreeting represents a method, it should be used in the same way that it is assigned (such as chinesegreeting), such as:
makegreeting (name); Well, with the idea, we're going to change the Greetpeople () method, so it should look like this: Public void Greetpeople (string name, * * * makegreeting) { makegreeting (name);}
Note that this position is usually placed in the type of parameter, but so far, we just think that there should be a parameter that can represent the method, and according to this idea to rewrite the Greetpeople method, now there is a big problem: What type of makegreeting parameter should be used to represent the method?
Note: It is no longer necessary to enumerate, because when assigning to makegreeting dynamically decide which method to use, whether it is chinesegreeting or englishgreeting, and within this two method, the use of " Morning "or" Good Morning "made a distinction.
Smart you should have thought, now is the time to entrust the appearance, but before the delegation, we look at the makegreeting parameter can represent the chinesegreeting () and the Englishgreeting () method signature:
Public void Englishgreeting (string name)publicvoid chinesegreeting (string name)
As name can accept the string type "true" and "1", but cannot accept the bool type of true and int type 11. the makegreeting parameter type definition should be able to determine the kind of method that makegreeting can represent, and further, that is, the parameter type and return type of the method that makegreeting can represent.
Thus, the delegate appears: It defines the kind of method that the makegreeting parameter can represent, that is, the type of the makegreeting parameter.
Note: If the above is a bit of a detour, I translate it to this: string defines the kind of value that the name parameter can represent, that is, the type of the name parameter.
The definition of a delegate in this example:
public delegate void Greetingdelegate (string name);
Can you compare the signature of the Englishgreeting () method above, except that the delegate keyword is added, the rest is not exactly the same?
Now, let's Change the Greetpeople () method again, as follows:
public void Greetpeople (string name, Greetingdelegate makegreeting) {
Makegreeting (name);
}
As you can see, the delegate greetingdelegate appears in the same position as the string, and the string is a type, then the greetingdelegate should also be a type, or class. But the way the delegate is declared and the class is completely different, what's the matter? In fact, a delegate compiles into a class when it is compiled. Because delegate is a class, you can declare a delegate anywhere you can declare a class. More content will be described below, now, take a look at the complete code for this example:
usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;namespaceconsoleapplication2{ Public Delegate voidGreetingdelegate (stringname);//Defining delegate Types classProgram {Private Static voidGreetpeople (stringName, Greetingdelegate makegreeting)//call method, call the method passed over{makegreeting (name); } Private Static voidEnglishgreeting (stringname) {Console.WriteLine ("Morning,"+name); } Private Static voidChinesegreeting (stringname) {Console.WriteLine ("Good Morning,"+name); } Static voidMain (string[] args) {greetingdelegate delegate1=NewGreetingdelegate (englishgreeting);//Statement andinstantiate a delegateDelegate1 + = chinesegreeting;//to bind a method to this delegate variable//the Englishgreeting and Chinesegreeting methods will be called successivelyGreetpeople ("Hong MaJu", delegate1); Console.WriteLine (); Delegate1-= englishgreeting;//to unbind a englishgreeting method//will only call chinesegreetingGreetpeople ("Red Horse Car", delegate1); Console.readkey (); } }}
The output is as follows:
Morning, Hong MaJu
Good morning, red horse car.
If Chinesegreeting and englishgreeting are in another class, the main function needs to be changed like this:
Static void Main (string[] args) { new Greetingmanager (); gm. Greetpeople ("Jimmy Zhang", englishgreeting); gm. Greetpeople (" Zhang Ziyang ", chinesegreeting);}
Example two:
Delegate intGetcalculatedvaluedelegate (intXinty); Static intAddcalculator (intXinty) {returnX +y; } Static intSubcalculator (intXinty) {returnX-y; } Static intCalculator (Getcalculatedvaluedelegate del,intXinty) {returndel (x, y); } Static voidMain (string[] args) {Console.WriteLine (Calculator (Addcalculator,Ten, -)); }
In the example above, the first parameter of the calculator function is a delegate. In fact, what calculator does with X and Y, it doesn't know how to handle X and Y is determined by getcalculatedvaluedelegate. So in the main method, we pass the Addcalculator method as a parameter to calculator, which means that Calculator uses addcalculator logic to process X and Y. This is also very image: Calculator said: "I do not know how to deal with X and Y, let del to deal with it!" So I threw X and Y to Del.
We now make a summary of the Commission:
A delegate is a class that defines a method's type so that it can be passed as a parameter to another method, which dynamically assigns the method to the parameter, avoids the large use of the If-else (Switch) statement in the program, and makes the program more extensible.
Using delegates, you can bind multiple methods to the same delegate variable, and when you call this variable (the word "call" is used here because the variable represents a method), you can call all the bound methods in turn.
Delegates in C #