Entrusted is a reference type in C #, similar to a function pointer in C / C . Unlike functional pointers, delegate is object-oriented, secure, and entrusting can reference static methods and instance methods, and function pointers can only reference static functions. The commission is mainly used for event handler and callback functions in .NET Framework.
A commission can be seen as a special class, so its definition can be placed in the same position like a conventional class. Like other classes, the commission must first define, then instantiate. Different from the class, instantiated entrustments do not have the corresponding terms (instantiated objects of the class), as a distinction we will instantiate the entrustment example.
Function pointer
A function is assigned to an entry address when compiling, which is called a function of a function, just as the pointer is the address of a variable.
Many functions of the function pointer, one of the most common purposes is to pass the pointer as a parameter to other functions. We can refer to the example below to further understand the function of the function pointer as a parameter:
# include
Int Max (int X, int y)
{{
Return (x> y? X: y);
}
IT MIN (int X, int y)
{{
Return (X)
}
IT SUB (int x, int y)
{{
Return (X Y);
}
int x, int y
{{
Return (X-Y);
}
Void test (int, int, int), int (* q) (int, int), int A, int b)
{{
Int Int1, int2;
IT1 = (* p) (a, b);
= (* q) (a, b);
Printf ("% D, / T% D / N", INT1, INT2);
}
Void main ()
{{
Test (MAX, MIN, 10, 3);
Test (SUB, Minus, 10, 3);
}
Objectively speaking, using function pointer as a function of its parameters If the function is directly called the function or directly put the function body of the called function in this main function. So why should I use a function pointer? Let's take a closer look that the main () function can find that the main () function calls the TEST function twice, the maximum minimum value is obtained before, and two sums of difference are obtained again. If we do not use a function pointer, do you use a Test function to complete this function with a method of calling a function directly in a Test function? Obviously, we must write two such TEST functions for main () function calls, although most code is still the same, just called the function name.
The above is just a simple example. In the actual life, the main () function will frequently call Test (), and each difference is only the function of completing, perhaps the first call will request two numbers. And poor, and next time you will ask for maximum and two sum, the third time, maybe a minimum and maximum, ... If you don't need a function pointer, how many of these Tests we need to write ( )function? Obviously, function pointers provide flexibility for our programming.
In addition, some places must use the function pointer to complete a given task, especially the callbacks of asynchronous operations and other structures that require anonymous callbacks. In addition, the implementation of the thread, the processing of the event, is difficult to complete if the support of the function pointer is not completed.
Type security
It can be seen from the above introduction that the function pointer is still necessary, and the above introduction also shows the necessity of delegate. So why don't I use a function pointer in C #, but to use the delegation? This involves another problem: C # is a type of security language. What is the type of security? The type of type herein refers to memory type security, that is, the type security code only accesss the memory location that is authorized to access. If the code accesses the memory at any offset, the offset exceeds the memory range of the public field belonging to the object, it is not a type of security code. Obviously the pointer does not belong to the type security code, which is why the C # uses a pointer must declare the unsafe.
So what is the adverse consequence of type inactive code? I believe that friends who are interested in security technologies must be familiar with the buffer overflow problem. By the buffer overflow attacker can run illegal programs to get certain permissions to attack the system or run the malicious code hazard system, which is a very very common problem. So what is the relationship between the buffer overflow and the function pointer? In fact, the attacker is to change the value to the malicious code address by the buffer overflow change to the malicious code address. We can take a look at the code below:
Void copy ()
{{
Char buffer [128];
........
Strcpy (Buffer, GetENV ("Home"))); // Home is Home Environment Variable in UNIX System
........
}
In the above code, if the number of home environment variables is greater than 128, the buffer overflow will generate a buffer overflow. If this buffer has another function return address, then this is that the address is possible to overwrite, and this is overwritten The address of the address is likely to be the address of malicious code, and the attacker may have a successful attack!
The above example is only one of the pointer problems, in addition to this, may write data to an error address due to the wrong management address, resulting in a crash of the program; it may also be suspended due to an improper assignment operation of the pointer Pointer; may also produce a problem of memory processes, memory leaks, and more.
This shows that the pointer is not type safe, and the function pointer is of course no exception, so there is no function pointer in C #, and the pointer variable is not recommended.
Delegate
The previous description fully demonstrates the necessity of delegate, then let's talk about why the entrusted is safe. The delegation and pointer in C # are different. The pointer does not pass MSIL, but also the reasons why the pointer is unsafe. Of course, the pointer can improve the speed of the program, but not to deal with the memory, but Have this job to CLR to complete. The CLR cannot block the unsafe code to call the unsafe code into the unit (non-managed) code or perform malicious operations. However, when the code is safe, the CLR security enforcement mechanism ensures that the code does not access the native code unless it has access to the local code.
Delegate to be derived from the base class System.deLegate, but the definition of the commission is not the same. Delegate definitions by keyword delegate:
Public Delegate Int MyDelegate (int X, int y);
The above code defines a new delegate that can be packaged any way to return to INT, with two int type parameters. Any method is whether the example method or a static method, as long as their signature (parameter type in a method) and the definition delegate are the same, they can be encapsulated into the delegate. This signature method is to ensure that the entrusted is one of the means of type security.
generated an instance of the entrustment and a class instance (object), if we have the following methods:
Public Int Sub (int X, int y)
{{
Return (X Y);
}
We can use the following code to get a delegate instance:
MYDELEGATE CALCULATIN = New MyDelegate (SUB);
Next we can use the Calculation to call the SUB method directly:
Calculation (10, 3);
Below we will use the delegate to rewrite a program to rewrite how to implement the functionality implemented by the function pointer 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)
}
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; Return;
}
}
}
Class Test
{{
Static void main ()
{{
Handler.Eventhandler (1, 10, 3);
Handler.EventHandler (2, 10, 3);
}
}