Directory
-
- Simulate process-oriented language functions as passing Parameters
- Multicast Delegation
- Anonymous Method
- Lambda expression
In the previous section, the delegation and events are briefly described. This section will separately describe the delegation and events.
- Simulate process-oriented language functions as passing Parameters
Anyone who uses C and other process-oriented languages knows that functions (methods) can be brought and called as parameters of another function. This technology is widely used in many fields: for example, callback functions in an embedded development environment. However, in object-oriented languages, a function is a member of a class and can only be accessed through objects. So, is there no way to solve the technical approach like the process-oriented method that only calls a function? Of course, there is a way. I have summarized the methods in step 2 in my learning process. One of them is to use delegation, and the other is to use interfaces. If you have a better method, let's talk about learning.
Not much nonsense.
From the above section [C # Delegate, event (1) http://www.cnblogs.com/Youhei/archive/2010/05/04/1727544.html] the description of the delegate shows that the delegate is a class and must have the same signature with the declaration delegate to initialize it. The following describes the solution to the above problem using a column.
First, create a console application and create a class. The method members in this class (which are defined as static for simplicity) will be used as the parameters for delegate initialization:
public class MathOper { public static double Multiply(double val) { return val * 2; } public static double Square(double val) { return val * val; } }
Then, other non-class definitions in the namespace match the delegate of the methods in the above class:
public delegate double DelegateFuction(double val);
Note: defining a Delegate in C # refers to defining a new class. The Delegate implementation is derived from the base class System. MulticastDelegate class, which is also derived from the System. Delegate class. C # The Compiler knows this class and uses its delegate syntax. This is an example of the cooperation between C # language and the base class. We do not need to know the specific execution conditions.
Next, you can create a call class that uses the above class and the delegate:
public class Counter { private double myValue; public double Value { set { this.myValue = value; } } public void Deal(DelegateFuction dele) { if (dele != null) { String str = "Deal value is:" + dele(this.myValue).ToString(); Console.WriteLine(str); } } }
The Value in this class receives incoming data. The Deal parameter of the method is delegated to the DelegateFuction type, and a delegate is required. The preceding two classes are available, finally, create an object call in the Main entry function of the Program class:
class Program { static void Main(string[] args) { Counter ct = new Counter(); ct.Value = 10; ct.Deal(new DelegateFuction(MathOper.Multiply)); //ct.Deal(MathOper.Multiply); ct.Deal(new DelegateFuction(MathOper.Square)); //ct.Deal(MathOper.Square); } }
Run and the result is:
You may be interested in the Code Annotated. In fact, since C #2.0, the use of delegation has been extended by delegation inference. To reduce user input, you only need to delegate the instance to transfer the address name, which becomes the delegate inference. Release the annotated code in the above Code to achieve the same effect as the upstream code.
In addition, when initializing the delegate, the method name is used, such as MathOper. Multiply, instead of MathOper. Multiply (); MathOper. Multiply () is the method execution.
First, create an interface:
public interface InterFaceFuction { double IFuction(double val); }
Then create a class that inherits from this interface:
Public class InterBase: InterFaceFuction {# region InterFaceFuction member public double IFuction (double val) {return val * 2 ;}# endregion}
Overload the Deal function in the Counter class above:
public void Deal(InterFaceFuction fun) { if (fun != null) { String str = "Deal value is:" + fun.IFuction(this.myValue).ToString(); Console.WriteLine(str); } }
Add the following in the Main method of the Progra class:
ct.Deal(new InterBase());
When an interface is used, the InterBase interface is used as a parameter to bring the IFuction Method to the Deal method of the Counter class to handle the requirement. Of course, it can also achieve the same goal by passing object references, but sometimes the delegate and interface methods are more practical. All code is provided:
Sample Code: using System; using System. collections. generic; using System. linq; using System. text; namespace ConsoleApplication1 {// delegate public delegate double DelegateFuction (double val); public class MathOper {public static double Multiply (double val) {return val * 2 ;} public static double Square (double val) {return val * val;} public class Counter {private double myValue; public double Value {se T {this. myValue = value ;}// delegate public void Deal (DelegateFuction dele) {if (dele! = Null) {String str = "Deal value is:" + dele (this. myValue ). toString (); Console. writeLine (str) ;}}// interface public void Deal (InterFaceFuction fun) {if (fun! = Null) {String str = "Deal value is:" + fun. IFuction (this. myValue ). toString (); Console. writeLine (str) ;}}// interface/* -------------------------------------------------- */public interface InterFaceFuction {double IFuction (double val);} public class InterBase: interFaceFuction {# region InterFaceFuction member public double IFuction (double val) {return val * 2;} # endregion}/* interval */class Program {static void Main (string [] args) {Counter ct = new Counter (); ct. value = 10; // ct. deal (new DelegateFuction (MathOper. multiply); ct. deal (MathOper. multiply); // ct. deal (new DelegateFuction (MathOper. square); ct. deal (MathOper. square); ct. deal (new InterBase ());}}}
In the preceding example, the delegate variables are initialized using an existing method when defining the delegate instance. This requires that the method already exists, however, if the method to initialize the delegate variable does not exist, or you do not need to initialize the delegate instance with an alternative method, you can use the anonymous method to initialize the delegate instance.
When you use an anonymous method to initialize a delegated instance, you need to use the delegate keyword to modify it, as shown below:
Delegate type delegate variable = delegate (parameter type parameter variable) {[anonymous method logic processing...]};
In the preceding example, the principal variable df is initialized using the MathOper. Multiply () method in the Main method. We can also initialize the principal variable as follows:
class Program { static void Main(string[] args) { Counter ct = new Counter(); DelegateFuction df = delegate(double val) { return val * 2; }; //DelegateFuction df = MathOper.Multiply; ... } }
The anonymous method reduces the amount of code writing. You can apply some external variables in the anonymous method. However, when using the anonymous method, you must pay attention to the following two points:
- (1). You cannot access Insecure code in an anonymous method or access parameters modified with the ref and out keywords outside the anonymous method.
- (2) The jump statement cannot be used in the anonymous method to jump outside the anonymous method, and vice versa.
Since C #3.0, we can further simplify the compilation of anonymous methods, that is, the lambda expression we will talk about next.
When using the lambda expression, define the delegate type as before, but it is slightly different when initializing the delegate instance. Let's take a look at the example first and change the Main in the "anonymous method" section slightly:
class Program { static void Main(string[] args) { Counter ct = new Counter(); //DelegateFuction df = delegate(double val) //{ // return val * 2; //}; DelegateFuction df = val => { return val * 2; }; ... } }
In the above Code, the equal sign after val is the λ operator, and val is the input parameter. If there are multiple parameters, You can enclose them in parentheses. Of course, parameters can also be defined.
Type, but not required, because the compiler knows the type of each parameter.
In the previous section, each delegate only contains one method call, that is, the number of calls to the delegate is equal to the number of calls to the method. If you use one delegate to call different methods, this is multicast delegate. Multicast delegation can contain multiple different methods. If you call multicast delegates, you can call multiple methods in sequence.
Transform the example in the previous section. The result is as follows (only the processing logic of the Main function in the Program class is transformed ):
class Program { static void Main(string[] args) { Counter ct = new Counter(); DelegateFuction df = MathOper.Multiply; df += MathOper.Square; ct.Value = 10; ct.Deal(df); //ct.Deal(new DelegateFuction(MathOper.Multiply)); //ct.Deal(MathOper.Multiply); //ct.Deal(new DelegateFuction(MathOper.Square)); //ct.Deal(MathOper.Square); //ct.Deal(new InterBase()); } }
In addition, it is worth noting that: "If you use multicast delegates, you should note that the sequence of the same delegate call method chain is not formally defined, therefore, you should avoid coding code that relies on calling methods in a specific order ". In addition, the multicast delegate contains a set of delegates called one by one. If an exception is thrown by a method called by the delegate, the entire call iteration stops.
Run the command. The result is as follows:
Strange! Why only the MathOper. Square () method is called? In fact, MathOper is used to execute the method chain of the df instance entrusted by DelegateFuction in the Main method. multiply () method and MathOper. the Square () method is called, but the multicast delegate only returns the return value of the last method in the method chain, so the output result is only MathOper. the data returned by the Square () method. Here, we must note that when using multicast delegate, the delegate return type must be marked as void, otherwise, only the return value of the last method in the method chain is returned.