Delegate in C #

Source: Internet
Author: User

C # delegation and event Introduction

Delegation and events are widely used in. Net Framework. However, it is not easy for many people who have been in contact with C # for a long time to better understand delegation and events. They are like a hacker. People who have passed the hacker think it is too easy, and people who have never seen the delegate and event will feel different (bi) panic and uncomfortable. In this article, I will use two examples to explain from a simple perspective what is delegation, why is delegation used, how events come from, and why ,. the significance of delegation, events, delegation, and events in the Net Framework to the Observer design pattern, and their intermediate code is also discussed.

Use a method as a method parameter

Let's look at the two simplest methods, no matter how the title is spoken or whether the delegate is actually something. They are just a greeting on the screen:

GreetPeople (name ){
EnglishGreeting (name );
}
EnglishGreeting (name ){
. WriteLine (+ name );
}

For the moment, no matter whether the two methods have any practical significance. GreetPeople is used to say hello to someone. When we pass the name parameter representing someone's name, such as "Jimmy", In this method, the EnglishGreeting method will be called and the name parameter will be passed again, englishGreeting is used to output "Morning, Jimmy" to the screen ".

Now let's assume that this program needs to be global. Oh, no. I am a Chinese. I don't understand what "Morning" means. What should I do? Okay, let's add a Chinese edition greeting method:

ChineseGreeting (name ){
. WriteLine (+ name );
}

At this time, GreetPeople also needs to be changed. Otherwise, how can we determine which version of Greeting method is suitable? Before proceeding, we 'd better define another enumeration as the basis for judgment:

{
English, Chinese
}

GreetPeople (name, Language lang ){
Swith (lang ){
Language. English:
EnglishGreeting (name );
;
Language. Chinese:
ChineseGreeting (name );
;
}
}

Okay, even though this solves the problem, it is easy to think of without saying that this solution has poor scalability. If we need to add Korean and Japanese Versions later, you have to modify the enumeration and GreetPeople () methods repeatedly to meet new requirements.

Before considering a new solution, let's look at the GreetPeople method signature:

GreetPeople (name, Language lang)

Let's just look at the string name. Here, string is a parameter type, and name is a parameter variable. When we assign the name string "jimmy", it represents the value of "jimmy; when we grant it "Zhang Ziyang", it also represents the value of "Zhang Ziyang. Then, we can perform other operations on this name in the method body. Ah, is this nonsense? I knew it when I first learned the program.

If you think about it again, if the GreetPeople () method can accept a parameter variable, this variable can represent another method. When we assign EnglishGreeting to this variable, it represents EnglsihGreeting () this method. When we assign ChineseGreeting to it, it also represents the ChineseGreeting () method. We name this parameter variable MakeGreeting, so it is not the same as when we assign a value to the name. When we call the GreetPeople () method, is this MakeGreeting parameter also assigned a value (ChineseGreeting or EnglsihGreeting )? Then, we can use MakeGreeting in the method body just like using other parameters. However, because MakeGreeting represents a method, it should be used in the same way as the method it is assigned (such as ChineseGreeting), for example:

MakeGreeting (name );

Now that we have the idea, let's change the GreetPeople () method. It should look like this:

GreetPeople (name, *** MakeGreeting ){
MakeGreeting (name );
}

Note that ***, this location should usually be placed in the parameter type, but so far, we just thought that there should be a parameter that can represent the method, and rewrite the GreetPeople method according to this idea. Now there is a big problem:This indicates the type of the MakeGreeting parameter of the method?

NOTE:Enumeration is no longer needed here, because when assigning values to MakeGreeting, you dynamically decide which method to use, whether it is ChineseGreeting or EnglishGreeting. Inside these two methods, we have already made a distinction between "morning" and "good morning.

You should have thought about it. Now it's time to delegate the game, but let's look at the ChineseGreeting () and EnglishGreeting () parameters that can be represented by the delegate () method signature:

EnglishGreeting (name)
ChineseGreeting (name)

As if the name can accept "true" and "1" of the String type, but cannot accept the same true of the bool type and 1 of the int type.The parameter Type Definition of MakeGreeting should be able to determine the types of methods that MakeGreeting can represent. Further, it is the parameter type and return type of the methods that MakeGreeting can represent.

As a result, the delegate appears:It defines the types of methods that can be represented by the MakeGreeting parameter, that is, the type of the MakeGreeting parameter.

NOTE:If the above sentence is a detour, I will translate it into this: string defines what the name parameter can represent.Type of ValueThat is, the type of the name parameter.

Definition of delegation in this example:

GreetingDelegate (name );

Can I compare it with the signature of the above EnglishGreeting () method? Except for the delegate keyword, are the rest identical?

Now let's change the GreetPeople () method again, as shown below:

GreetPeople (name, GreetingDelegate MakeGreeting ){
MakeGreeting (name );
}

As you can see, the position of the delegate GreetingDelegate is the same as that of the string, and the string is a type, so GreetingDelegate should also be a type or Class ). However, the delegate declaration method is completely different from the class. What is this? In fact, the Delegate will indeed be compiled into classes during compilation. Because Delegate is a class, delegates can be declared wherever classes can be declared. For more information, see the complete code of this example:

Using System;
Using System. Collections. Generic;
Using System. Text;

Namespace Delegate {
// Define the delegate, which defines the types of methods that can be represented
GreetingDelegate (name );
Class Program {

Private static void EnglishGreeting (string name ){
Console. WriteLine ("Morning," + name );
}

Private static void ChineseGreeting (string name ){
Console. WriteLine ("good morning," + name );
}

// Note that this method accepts a GreetingDelegate method as a parameter.
Private static void GreetPeople (string name, GreetingDelegate MakeGreeting ){
MakeGreeting (name );
}

Static void Main (string [] args ){
GreetPeople ("Jimmy Zhang", EnglishGreeting );
GreetPeople ("Zhang Ziyang", ChineseGreeting );
Console. ReadKey ();
}
}
}

The output is as follows:
Morning, Jimmy Zhang
Good morning, Zhang Ziyang

We now make a summary of the delegation:

A delegate is a class that defines the type of a 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.

Bind method to delegate

Do you feel like waking up? So, are you wondering: In the above example, I don't have to assign a value to the name parameter directly in the GreetPeople () method. I can use the variable like this:

Main ([] args ){
Name1, name2;
Name1 =;
Name2 =;

GreetPeople (name1, EnglishGreeting );
GreetPeople (name2, ChineseGreeting );
. ReadKey ();
}

Since the same status of the delegate GreetingDelegate and the type string is defined as a parameter type, can I use the delegate as well?

Main ([] args ){
GreetingDelegate delegate1, delegate2;
Delegate1 = EnglishGreeting;
Delegate2 = ChineseGreeting;

GreetPeople (, delegate1 );
GreetPeople (, delegate2 );
. ReadKey ();
}

As expected, this is fine, and the program is output as expected. Here, I want to talk about the Delegate Feature different from the string feature: You can assign multiple methods to the same delegate, or bind multiple methods to the same delegate, when this delegate is called, the bound methods are called in sequence. In this example, the syntax is as follows:

Main ([] args ){
Delegate1;
Delegate1 = EnglishGreeting; delegate1 + = ChineseGreeting;
GreetPeople (, delegate1 );
. ReadKey ();
}

Output:
Morning, Jimmy Zhang
Good morning, Jimmy Zhang

In fact, we can also bypass the GreetPeople method and directly call EnglishGreeting and ChineseGreeting through delegation:

Main ([] args ){
Delegate1;
Delegate1 = EnglishGreeting; delegate1 + = ChineseGreeting;
Delegate1 ();
. ReadKey ();
}

 

NOTE:This is no problem in this example, but looking back at the above definition of GreetPeople (), we can do some work that needs to be done for both engshihgreeting and ChineseGreeting, I omitted it for convenience.

Note that "=" is used for the first time, which is the syntax of value assignment; "+ =" is used for the second time, which is the binding syntax. If "+ =" is used for the first time, the compilation error "using unassigned local variables" will occur.

We can also use the following code to simplify this process:

Delegate1 = (EnglishGreeting );
Delegate1 + = ChineseGreeting; // bind the delegate variable to another method.

As you can see, it should be noted that the first statement of this Code is similar to instantiating a class. You can't help but think that the "+ =" Compilation error cannot be used when the delegate is bound for the first time, this method may be used to avoid:

Delegate1 = ();
Delegate1 + = EnglishGreeting; delegate1 + = ChineseGreeting; // bind the delegate variable to another method.

But in fact, there will be a compilation error: the "GreetingDelegate" method does not use the "0" parameter overload. Although this result is a bit frustrating, the compilation prompt "no overload of 0 Parameters" reminds us of the class constructor again. I know that you may not be able to find out what it is, but before that, we need to finish introducing basic knowledge and applications.

Since a delegate can bind a method, there should be a way to unbind the method. It is easy to think that this syntax is "-= ":

Main ([] args ){
Delegate1 = (EnglishGreeting );
Delegate1 + = ChineseGreeting;
GreetPeople (, delegate1 );
. WriteLine ();

Delegate1-= EnglishGreeting; GreetPeople (, delegate1 );
. ReadKey ();
}
Output:
Morning, Jimmy Zhang
Good morning, Jimmy Zhang
Good morning, Zhang Ziyang

Let's summarize the delegation again:

You can use a delegate to bind multiple methods to the same delegate variable. When you call this variable (the word "call" is used here because this variable represents a method ), you can call all bound methods in sequence.

Related Article

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.