Introduction
The delegate is a reference type in C #, similar to the function pointer in C/C ++. Unlike function pointers, delegation is object-oriented and type-safe, and can reference static methods and instance methods. function pointers can only reference static functions. Delegation is mainly used for event handlers and callback functions in. NET Framework.
A delegate can be considered as a special class, so its definition can be put in the same position as a regular class. Like other classes, the delegate must be defined before instantiation. Different from the class, the instantiated delegate does not have the corresponding terminology (class instantiation is called an object). As a distinction, the instantiated delegate is called a delegate instance.
Function pointer
A function is assigned an entry address during compilation. This entry address is called a function pointer, just as the same pointer is a variable address.
Function pointers have many purposes. One of the most common uses is to pass pointers as parameters to other functions. We can refer to the following example to further understand the function pointer as a parameter:
# Include <stdio. h> Int max (int x, int y) { Return (x> Y? X: Y ); } Int min (int x, int y) { Return (x <Y? X: Y ); } Int sub (int x, int y) { Return (x + y ); } Int minus (int x, int y) { Return (x-y ); } Void test (INT (* p) (INT, INT), INT (* q) (INT, INT), int A, int B) { Int int1, int2; Int1 = (* p) (A, B ); Int2 = (* q) (A, B ); Printf ("% d, \ t % d \ n", int1, int2 ); } Void main () { Test (max, min, 10, 3 ); Test (sub, minus, 10, 3 ); } |
Objectively speaking, if a function using a function pointer as its parameter directly calls a function or directly places the called function body in this main function, it can also implement its function. So why should we use function pointers? Let's take a closer look at the above main () function and we can find that the main () function calls the test function twice, and the maximum and minimum values are obtained the previous time, the sum and difference of the next two numbers are obtained. If we use the test function to call the function directly in the test function instead of using the function pointer, can we use the test function to complete this function? Obviously not. We have to write two such test functions for the main () function to call. Although most of the Code is the same, only the called function names are different. The above is just a simple example. In real life, the main () function may frequently call test (), and the difference between each function is that the function is different, maybe the first call requires finding the sum and difference of two numbers, and the next call requires finding the sum of the maximum and two numbers. The third call may be the minimum and maximum values ,......, How many such test () functions do we need to write without using function pointers? Obviously, function pointers provide flexibility for our programming.
In addition, in some cases, the function pointer must be used to complete a given task, especially for Asynchronous Operation callback and other structures that require anonymous callback. In addition, such as thread execution and event processing, it is difficult to complete if function pointer support is missing.
Type Security
From the above introduction, we can see that the proposal of the function pointer is still necessary. The above introduction also illustrates the necessity of the existence of the delegate. So why does C # use a delegate instead of a function pointer? This involves another problem: C # Is a type-safe language. What is type security? Here, the type security refers to the memory type security, that is, the type security code only accesses the authorized memory location. If the code accesses the memory at any offset that exceeds the memory range of the public field of the object, it is not a type-safe code. Obviously, pointers do not belong to type-safe code, which is why C # must declare unsafe when using pointers.
So what are the negative consequences of type-Insecure code? I believe that those who are interested in security technology will be very familiar with the buffer overflow problem. Through the buffer overflow, attackers can run illegal programs to gain certain permissions to attack the system or directly run malicious code to harm the system, in UNIX, this is a very common problem. So what is the relationship between buffer overflow and function pointers? In fact, attackers execute malicious code by changing the returned address value to the malicious code address through buffer overflow. Let's look at the following code:
Void copy ()
{
Char buffer [128];
........
Strcpy (buffer, getenv ("home"); // home is the home environment variable in UNIX.
........
}
In the above Code, if the number of characters in the home environment variable is greater than 128, a buffer overflow occurs. If the buffer has another function return address before, if this is the address, it may be overwritten. The character that overwrites this address may be the address of the malicious code, and the attacker may be able to attack successfully!
The above example is only one of the pointer problems. In addition, it may also cause the program to crash due to incorrect management addresses and writing data to wrong addresses; it may also cause floating pointers due to improper pointer assignment operations, memory out-of-bounds, memory leakage, and other problems.
It can be seen that pointers are not of type security and function pointers are no exception, so function pointers are not used in C # And pointer variables are not recommended.
Delegate
The previous descriptions fully prove the necessity of delegation, so let's talk about why delegation is of type security. In C #, the delegate and pointer are different. Instead of using msil, the pointer directly deals with the memory. This is also the reason why the pointer is insecure. Of course, it is also the reason why the pointer can improve the program running speed; the delegate does not deal with the memory, but is done by the CLR. CLR cannot prevent unsafe code from being called to local (unmanaged) code or performing malicious operations. However, when the code is type-safe, the CLR security force mechanism ensures that the Code does not access the local code unless it has the permission to access the local code.
The delegate is derived from the base class system. Delegate, but the delegate definition is not the same as that of the general class. The delegate definition is defined by the keyword delegate:
Public Delegate int mydelegate (int x, int y );
The code above defines a new delegate, which can encapsulate any method that returns an int with two int type parameters. For any method, whether it is an instance method or a static method, as long as their signature (the order of parameter types in a method) is the same as the defined delegate, they can all be encapsulated in the delegate. This signature method is one of the methods to ensure delegate security.
The method for generating a delegated instance is similar to that for generating a class instance (object). Suppose we have the following methods:
Public int sub (int x, int y)
{
Return (x + y );
}
We can use the following code to obtain a delegated instance:
Mydelegate calculatin = new mydelegate (sub );
Next, we can directly use calculation to call the sub method:
Calculation (10, 3 );
Next we will use the delegate to rewrite the above program to see how to implement the function implemented by the function pointer through the delegate in C:
Using system; Class mathclass { Public static int max (int A, int B) { Return (A> B? A: B ); } Public static int min (int A, int B) { Return (A <B? A: B ); } Public static int sub (int A, int B) { Return (A + B ); } Public static int minus (int A, int B) { Return (a-B ); } } Class Handler { Private delegate int calculation (int A, int B ); Private Static Calculation [] mycalculation = New Calculation [2]; Public static void eventhandler (int I, int A, int B) { Switch (I) { Case 1: Mycalculation [0] = new calculation (mathclass. max ); Mycalculation [1] = new calculation (mathclass. min ); Console. writeline (mycalculation [0] (a, B )); Console. writeline (mycalculation [1] (a, B )); Break; Case 2: Mycalculation [0] = new calculation (mathclass. sub ); Mycalculation [1] = new calculation (mathclass. Minus ); Console. writeline (mycalculation [0] (a, B )); Console. writeline (mycalculation [1] (a, B )); Break; Default: Return; } } } Class Test { Static void main () { Handler. eventhandler (1, 10, 3 ); Handler. eventhandler (2, 10, 3 ); } } |
We can also declare a delegate array, just like declaring an object array. In the above example, we use the delegate array. A delegate can also encapsulate multiple methods (Multicast delegate, often used in conjunction with the event handler), as long as the signature of these methods is correct. The return value of a multi-channel broadcast delegate is generally void, because a delegate can only have one return value. If a delegate whose return value is not void encapsulates multiple methods, only the returned values of the final encapsulated method can be obtained, which may be inconsistent with the original intention of the user and may cause inconvenience to management. If you want to return multiple values through the delegate, it is best to use the delegate array so that each delegate can encapsulate a method and return a value respectively.
Event
In C #, the most basic use of delegation is to process events. An event is a message sent by an object to send a notification. In other words, an event is a signal that needs to be processed in a program.
The event definition is declared with the keyword event, but a multi-channel broadcast delegate must exist before the event is declared:
Public Delegate void calculate (int x, int y); // The Void-returned delegate automatically becomes a multi-channel broadcast delegate;
Public event calculate oncalculate;
From the delegate instance in the preceding section and the event Declaration, we can see that the event declaration only has more keywords than the delegate instance declaration, in fact, an event can be considered as a multi-channel broadcast delegate customized for the event processing process. Therefore, after an event is defined, we can pre-define the event or cancel an event by adding the operator + = to the event, these operations are the same as those of the delegated instance. Unlike the delegated instance, operator = is invalid for events, that is
Oncalculate = new calculate (sub); // invalid
This is because the preceding statement deletes all other methods encapsulated by oncalculate, which encapsulates the unique method specified by this statement and can delete all other methods in a reservation, which leads to confusion.
Callback Function
A callback function is the code that helps an unmanaged DLL function complete a task in a hosted application. The call to the callback function is indirectly passed to the hosted implementation through a DLL function in the hosted application. Among the various DLL functions called by the platform, some functions require that the callback functions in managed code be correctly run. The callback function is only used for delegation, so it is not described too much here. For details, refer:
From: http://blog.csdn.net/lotusswan/archive/2003/11/04/19931.aspx