9.1 declaration and assignment of delegation
Delegate is a type of storage function reference.
The definition of a delegate specifies a return type and a list of parameters that tell the compiler which types of methods the delegate can point to.
After defining a delegate, you can create an instance of the delegate (declare a variable of the delegate type), and then assign a function with the same return type and parameter list as the delegate to the variable.
There are two steps to use delegation:
Definition
Declaration (variable)
The use of structure and enumeration can be divided into definition and declaration. Integer type array type string type declare variables directly, because the definition of type has been completed (the definition has been completed in CLR).
namespace c_sharp_001 { //The definition of a delegate is similar to that of a function, with the following differences: //To define a delegate, you need to add the delegate keyword //The definition of a delegate does not require a structure public delegate double MyDelegate(double param1, double param2); class Program { //The definition of delegation can also be in class private delegate string GetAString(); static double Multiply(double param1, double param2) { return param1 * param2; } //Define a Main method static void Main(string[] args) { MyDelegate de;//Declare a variable using the definition of a delegate de = Multiply;//When assigning a delegate variable (the delegate variable points to a function), the return value and parameter list must be the same Console.WriteLine(de(5.0, 2.0)); int x = 10; //GetAString getXString = new GetAString(x.ToString); / / give the method name to the constructor of a delegate / / getXString points to ToString method in X GetAString getXString = x.ToString; string s = getXString();//Give the method name directly to the delegate instance //string s = getXString.Invoke(); / / call the method Console.WriteLine(s) referenced by getXstring through the invoke method; Console.ReadKey(); } } } namespace c_sharp_practice04 { class Program { static void Main(string[] args) { //Use delegate type as parameter of method PrintString method = Method1; PrintStr(method); method = Method2; PrintStr(method); Console.ReadKey(); } private delegate void PrintString(); static void PrintStr(PrintString print) { print(); } static void Method1() { Console.WriteLine("Method1"); } static void Method2() { Console.WriteLine("Method2"); } } }
9.2 predefined delegation types
9.2.1Action delegation
The Action delegate refers to a method with no return value. It can specify multiple parameter types of the method pointed to by Action through generics (passing 0-16 parameter types).
Action
Action<in T>
Action<in T1,in T2>
Action<in T1,in T2 .... inT16>
namespace c_sharp_practice04 { class Program { static void PrintString() { Console.WriteLine("PrintString"); } static void PrintString(string str) { Console.WriteLine(str); } static void PrintInt(int i) { Console.WriteLine(i); } static void Print(int i,int j,string str) { Console.WriteLine(i+j+str); } static void Main(string[] args) { Action a = PrintString;//Action is a built-in (predefined) delegation type. It can point to a method that has no parameters and returns no / / value. Action<int> b = PrintInt;//Specify a generic type after the Action to specify the parameters of the method pointed to by the Action delegate type Action<string> c = PrintString;//Two PrintString methods are defined, and the system will automatically find the matching method Action<int, int, string> d=Print; d(1, 2, "Is the sum of the output"); Console.ReadKey(); } } } 9.2.2Func Entrust Func Refers to a method with a return value, which can pass 0~16 Parameter types, and a return type. Func<out TResult> Func<in T,out TResult> Func<int T1,inT2,,,,,,in T16,out TResult> namespace c_sharp_practice04 { class Program { static int Text1() { return 1; } static int Text2(string str) { Console.WriteLine(str); return 1; } static void Main(string[] args) { Func<int> a = Text1;//Generics in Func specify the return type of the method Func<string, int> b = Text2;//After Func, there can be 0-16 parameter types and one return type (at the end) } } }
9.2.3 bubble sorting with delegation extension
namespace c_sharp_practice04 { class Employee { public string Name { get; private set; } public int Salary { get; private set; } public Employee(string name,int salary) { this.Name = name; this.Salary = salary; } public static bool Compare(Employee e1,Employee e2) { if (e1.Salary > e2.Salary) return true; return false; } public override string ToString() { return Name + ":" + Salary; } } } namespace c_sharp_practice04 { class Program { //Only one type of data can be sorted static void Sort(int[] sortArray) { bool swapped = true; do { swapped = false; for (int i = 0; i < sortArray.Length - 1; i++) { if (sortArray[i] > sortArray[i + 1]) { int temp = sortArray[i]; sortArray[i] = sortArray[i + 1]; sortArray[i + 1] = temp; swapped = true; } } } while (swapped); } //Through delegation, it is extended to general bubble sorting of all types of data. static void CommonSort<T>(T[] sortArray,Func<T,T,bool> compareMethod) { bool swapped = true; do { swapped = false; for (int i = 0; i < sortArray.Length - 1; i++) { if (compareMethod(sortArray[i],sortArray[i+1])) { T temp = sortArray[i]; sortArray[i] = sortArray[i + 1]; sortArray[i + 1] = temp; swapped = true; } } } while (swapped); } static void Main(string[] args) { Employee[] employees = new Employee[] { new Employee("asdf",120), new Employee("wdft",999), new Employee("qadg",345), new Employee("ipjk",12434), new Employee("cvnm",22), new Employee("egyu",2324) }; CommonSort<Employee>(employees, Employee.Compare); foreach(var emp in employees) { Console.WriteLine(emp);//Calling ToString method by default } Console.ReadKey(); } } }
9.2.4 multicast delegation
The delegates used before contain only one method call, but delegates can also contain multiple methods, which are called multicast delegates. Multiple methods can be called in sequence by using multicast delegation. Multicast delegation can only get the (return) result of the last method called, so we usually declare the return type of multicast delegation as void.
Action action1 = Test1;
action2+=Test2;
action2-=Test1;
A multicast delegate contains a collection of delegates that are called one by one. If an exception is thrown by one of the methods called by the delegate, the entire iteration will stop.
namespace c_sharp_practice04 { class Program { static void Text1() { Console.WriteLine("Text1"); } static void Text2() { Console.WriteLine("Text2"); } static void Main(string[] args) { Action a = Text1; a += Text2;//Add a reference to a delegate a(); a -= Text1;// Console.WriteLine("-----"); a(); a -= Text2; //a(); / / when a delegate does not point to any method, an exception null will appear during the call. Console.ReadKey(); } } }
Get the delegation of all methods in the multicast delegation.
Action a1 = Method1;
a1+=Method2;
Delegate[] delegates=a1.GetInvocationList();
foreach(delegate d in delegates){
//d();
d.DynamicInvoke(null);
}
Traverse all the delegates in the multicast delegate, and call separately
namespace c_sharp_practice04 { class Program { static void Text1() { Console.WriteLine("Text1"); } static void Text2() { Console.WriteLine("Text2"); } static void Main(string[] args) { Action a = Text1; a += Text2;//Add a reference to a delegate Delegate[] delegates = a.GetInvocationList();//Get all delegates in a multicast delegate foreach(Delegate de in delegates) { de.DynamicInvoke();//Traverse all obtained delegates, call separately } Console.ReadKey(); } } }
9.2.5 anonymous delegation
Before we use delegation, we define a method first, and then give the method to the delegate instance. But there is another way to use delegation, instead of defining a method, which should be anonymous (method has no name).
Func<int, int, int> plus = delegate (int a, int b) {//Any place where delegate variables are used can be assigned anonymously int temp = a + b; return temp; }; int res = plus(34, 34); Console.WriteLine(res);
In this case, the method to be referenced is written directly at the back. The advantage is to reduce the code to be written and the complexity of the code. Mostly used for callback.
9.2.6 lambda expression
Lambda expressions can be used instead of anonymous methods. Lambda expressions can be used wherever there is a delegate parameter type. 9.2. The example of 5 can be modified as follows:
Func<int, int, int> plus = (arg1, arg2) => { int temp = arg1 + arg2; return temp; }; int res = plus(34, 34); Console.WriteLine(res);
The left side of the Lambda operator "= > lists the required parameters. If it is a parameter, you can write a = > directly (the parameter name is defined by yourself). If there are multiple parameters, use brackets to enclose them. The interval between parameters is.
If you need more than one statement in the implementation code of a Lambda expression, you must add curly braces and return statements. However, if there is only one statement in a Lambda expression, curly braces and return statements are not required in the method block, and the compiler will automatically add a return statement.
Func<double, double> square = x => x * x; Func<double, double> square = x => { return x * x; };
Through Lambda expressions, you can access variables outside the Lambda expression block. This is a very good function, but it can also be very dangerous if not used correctly. Example:
int somVal = 5; Func<int, int> f = x => x + somVal; Console.WriteLine(f(3));//8 somVal = 7; Console.WriteLine(f(3));//10
The result of this method is not only controlled by parameters, but also by somVal variables. The result is uncontrollable, which is prone to programming problems. You should be careful when using it.