C ා basic part - entrustment

preface

In this chapter, I mainly use this series of C basic chapters to sort out the past study notes, summarize and understand more thoroughly.

In. Net development, we often encounter and use delegation. If you can master and use it flexibly, you will be able to easily in programming. Then for many developers who have not been exposed to C for a long time, it is not easy to understand delegation and events better.

This section is mainly about the definition, use, multicast, generic, anonymous methods, Func and Action, Lambda, and discusses them.

explain

In short, it is an object that can pass a method as a parameter, and it also knows how to call the method, and it is also the "interface" with the smallest granularity (constraining the signature pointing to the method).

start

1. Definition of delegation

Delegate: is a type that defines a method signature. When you instantiate a delegate, you can associate its instance with any method that has a compatible signature. Methods can be called through a delegate instance.

Here is a quote from a netizen:

Someone has three sons. Let them take one thing with them to go out and bring back one of their prey.
The above sentence can be understood as the father's entrustment to his son: prey method (tool a tool) -- > delegate prey (return value) brings back prey (delegate name) (tool (parameter type) x) -- > delegate int getValue (int i)
There are different ways for three people to execute the entrustment
 Rabbit hunting (tool bow) - public static int getvalue1 (int i) {return I;}
Pheasant buy (tool money) - public static int getvalue2 (int i) {return I * 2;}
Wolf Trap - public static int getvalue3 (int i) {return I * I;}

2. Simple use

A delegate type defines a class of methods that can be called when instantiating the type. These methods contain the same return type and the same parameters (the number of types and parameters is the same)

For example: define a delegation

delegate int Calculator (int x);

This delegate applies to methods that have an int return type and an int type parameter.

static int Double (int x) { return x * 2; }

Create a delegate instance and assign the method to the delegate instance

Calculator c = new Calculator(Double);
//Or another way
Calculator c = Double;

Call through delegate instance

int result = c(2);

3. Multicast delegation

In the development process, we sometimes have to call a delegate and execute multiple methods at the same time, so we can consider multicast delegation. Calling multiple delegates requires multiple display calls to this delegate. All delegate instances can contain multiple methods to implement multicast function.

For example, multicast is like a group of programmers filling in their job application intention on the instant employment website. One day, a company released a job that just matched their job application intention, and then all the job seekers were informed that "there is a good job to recruit, you can directly apply to go to work!".
In other words, a delegate instance can point not only to one method, but also to multiple methods.
Multicast delegation provides a hook mechanism similar to pipeline. As long as the delegation is loaded on the pipeline, it will be executed in sequence. Because all delegates inherit from MulticastDelegate, all delegates have multicast characteristics
        //Declare a delegate whose return value is void
        public delegate void Greetings(String name);

        public static void Hello(String name)
        {
            Console.WriteLine("Hello!, {0}!", name);
        }

        public static void GoodBye(String name)
        {
            Console.WriteLine("bye, {0}!", name);
        }

        public static void Main()
        {
            Greetings greetings = Hello;
            //Use + = to add a method to a delegate
            greetings += GoodBye;
            String name = "AI Sanyuan";
            Console.WriteLine("This is a call method:");
            //First way of execution
            greetings(name);
            //Second way of execution
            Console.WriteLine("This is another way to use it");
            //Returns the list of calls for the delegate.
            Delegate[] delegates = greetings.GetInvocationList();
            //Note that the delegates list here stores delegates of type Greetings
            foreach (Greetings greeting in delegates)
            {
                greeting(name);
            }
            Console.ReadKey();
        }

explain:

  • If it is a multicast delegate, the signature of the delegate must return void. Otherwise, where should the return value go? When a delegate contains only one method, the declaration of its return type can be found through the encapsulated method, not necessarily void. In fact, if the compiler finds that a delegate returns void, it automatically assumes that it is a multicast delegate.

  • "+ =" to add, "- =" to remove method calls from delegates

4. Generic delegation

In the previous chapters, we have learned what is generic paradigm , so it's also convenient for us to understand the generic delegate. In short, it's a delegate with generic parameters.

		public delegate T Calculator<T>(T arg);
        static int Double(int x) { return x * 2; }

        static class Utility
        {
            public static void Calculate<T>(T[] values, Calculator<T> c)
            {
                for (int i = 0; i < values.Length; i++)
                    values[i] = c(values[i]);
            }
        }
        static void Main(string[] args)
        {
            int[] values = { 11, 22, 33, 44 };

            Utility.Calculate(values, Double);
            foreach (int i in values)
                Console.Write(i + " "); // 22 44 66 88
            Console.ReadKey();
        }

5. Anonymous method

Anonymous method is a method declared inline when initializing a delegate.

Each time you instantiate a delegate, you need to define the method that the delegate calls in advance. To simplify this process, C ා 2.0 began to provide anonymous methods to instantiate delegates. In this way, when we instantiate a delegate, we can "write as you use" its instance methods.

    static string GetNumber(string str)
    {
        return str;
    }
    delegate string DelNumber(string str);
    static void Main(string[] args)
    {
        //Declare a named method named GetNumber
        DelNumber delNumber1 = GetNumber;
        Console.WriteLine(delNumber1("This is the method of naming"));

        //Anonymous method, not defined elsewhere, but directly written in the instantiation code
        DelNumber delNumber2 = delegate (string str)
        {
            return str;
        };
        Console.WriteLine(delNumber2("This is an anonymous method call"));
        Console.ReadKey();
    }

    #endregion

From the simple example above, we can see that:

Syntax of anonymous method: keyword delegate {parameter list} {statement block}

delegte { Paramters} {ImplementationCode}

		delegate (string str)
        {
            return str;
        };

The format used is:

Delegate class name delegate instance name = delegate (args) {method body code};

		 delegate string DelNumber(string str); //Return type of delegate type
        //Anonymous method, not defined elsewhere, but directly written in the instantiation code
        DelNumber delNumber2 = delegate (string str)
        {
            return str;                         //Return a string type according to the return type
        };

This allows you to write methods directly into your instantiation code, without having to define them in another place. Of course, anonymous delegates are not suitable for the definition of delegates that require multiple methods. It should be noted that the anonymous method is not really "nameless", but the compiler automatically takes a name for us.

You can use anonymous methods in the following places:

  • Initialization expression when declaring delegate variable.
  • To the right of the assignment statement when combining delegates.
  • Add an event to the delegate on the right side of the assignment statement.

6. Fund and Action delegation

Before, when using delegation, we always defined a delegation type, and then defined a delegation field or variable using the self-defined delegation. In the following programming languages, a new feature is added. C ා language defines two commonly used delegates for us in advance, one is Func, the other is Action, which also brings Lambda, which makes the definition and use of delegates easier and makes it more flexible to introduce delegates into C ා programming later.

Action delegation

In C ා and predefined a delegate type Action, the basic feature is that it can execute a method without return value and parameters. It is a kind of delegate without output parameter, but the input parameter can be any type in C ා, that is, the method can be executed in the form of delegate.

    static void printString()
    {
        Console.WriteLine("Hello World");
    }
    static void printNumber(int x)
    {
        Console.WriteLine(x);
    }
    static void Main(String[] args)
    {
        //Basic use of Action
        Action a = printString;
        a(); // Output Hello World
        //Action points to a method with parameters
        Action<int> b = printNumber; // Define a function C × number that points to the parameter int
        b(5); // Output result 5
    }

Action can be specified by generics. The method pointed to has 0 - 16 parameters

Action < int, int, string, bool, etc. >

Func Commission

Func is also a pre-determined delegate. It is a delegate that returns a value, passing 0-16 parameters, in which both the input parameter and the return value are represented by generics.

  		static int GetNumber()
        {
            return 1;
        }
        static int GetNumber(string str)
        {
            return 1;
        }
        static void Main(string[] args)
        {
            Func<int> a = GetNumber; // Define a Func delegate that points to a method that returns an int type
            Console.WriteLine(a());
            Func<string, int> b = GetNumber; // The last parameter in the generic represents the return value type.
            Console.WriteLine(b("Hello"));
        }	

Note: func < string, int > the last parameter indicates the return value type, and the previous ones are all parameter types.

7. Lambda expression

Although anonymous method is very convenient to use, it's a pity that she has become popular for a long time. It's rarely seen today because the delegate keyword limits the extension of her use. Since C ා 3.0, she has been replaced by lambda expressions, which are easier to use. Lambda expressions are essentially improved anonymous methods.

In anonymous methods, the delegate keyword is a bit redundant because the compiler knows to assign our methods to delegates. Therefore, it is easy to convert the steps of anonymous methods to lambda expressions: 1. Delete the delegate keyword. 2. Put lambda operator = > between parameter list and anonymous method body.

DelNumber delNumber2 = delegate (string str){ return str;}; //Anonymous Methods 

DelNumber delNumber2 =  (string str) =>{ return str;}; //Lambda method

The inspiration of Lambda expression comes from the expression of Lambda integral function in mathematics, such as the following figure:

Lambda expressions use the = > symbol to represent the arrows.

In the above comparison example, Lambda can be further simplified

delegate string DelNumber(string str); //Return type of delegate type
DelNumber delNumber2 =  (string str) =>{ return str;}; //Lambda method
DelNumber delNumber3 =         (str) =>{ return str;}; //Omit type parameter
DelNumber delNumber4 =           str =>{ return str;}; //Omit type parameters (if there is only one implicit type parameter, you can omit the surrounding parentheses)
DelNumber delNumber5 =           str =>  str; //Replace the statement block with the expression after the return keyword (if there is only one return statement, you can replace the statement block with the expression after the return keyword)

Nowadays, Lambda expressions have been applied in many places, such as expression bodied methods, automatic read-only attribute expressions, etc.

Lambda expressions can be divided into two forms:

1. Expression Lambda
This can be used when anonymous functions have only one line of code. For example:

DelNumber delNumber= (s4, s5) => s4.Age <= s5.Age;

Where the = > symbol represents a Lambda expression, with parameters on the left and statements to return or execute on the right. Parameters should be placed in parentheses. If there is only one parameter, parentheses can be omitted for convenience. When there are multiple parameters or no parameters, parentheses cannot be omitted.

Compared with anonymous functions, in the expression Lambda, the curly braces {} and return keywords of the method body are omitted.

It also uses the expression Lambda, which is a generalization of Lambda expression and a syntax sugar provided by C ා 6 compiler.

2. Statement Lambda
When anonymous functions have multiple lines of code, only statement Lambda can be used. For example, the above expression Lambda can be rewritten as the statement Lambda:

DelNumber delNumber= (s4, s5) => 
{
    //Other codes are omitted here
    return s4.Age <= s5.Age;
};

Statement Lambda cannot omit {} and return statements.

Complete example

        delegate string DelNumber(string str); //Return type of delegate type
        static void Main(string[] args)
        {

            DelNumber delNumber2 = (string str) => { return str; }; //Lambda method
            DelNumber delNumber3 = (str) => { return str; }; //Omit type parameter
            DelNumber delNumber4 = str => { return str; }; //Omit type parameters (if there is only one implicit type parameter, you can omit the surrounding parentheses)
            DelNumber delNumber5 = str => str; //Replace the statement block with the expression after the return keyword (if there is only one return statement, you can replace the statement block with the expression after the return keyword)

            Console.WriteLine(delNumber2("lambda"));

            Console.WriteLine(delNumber3("lambda"));
            Console.WriteLine(delNumber4("lambda"));
            Console.WriteLine(delNumber5("lambda"));
            Console.ReadKey();
        }

Note: the parentheses can be omitted for one parameter. Multiple parameters must be parentheses, but there are no parameters. A set of empty parentheses must be used

For example: (parameter, parameter) = > {statement} or expression
       (parameter) = > {statement} or expression
        Parameter = > {statement} or expression
        () = > {statement} or expression

summary

  1. Delegation is equivalent to using a method as another method parameter. At the same time, it can be used to bridge two methods that cannot be called directly, such as cross thread method calls in multi-threaded.
  2. Be familiar with when to use delegation, when using event design pattern, when you need to encapsulate static methods, when you need convenient combination and other situations, you can use it.
  3. If there is something wrong or incomprehensible, I hope you can correct it, ask questions, discuss it together, keep learning and make progress together.
  4. In the next section, we will briefly introduce the events and summarize them.

reference resources file C diagram course

Note: search for official account [DotNet Technology Valley] - reply [C# diagram], available C diagram course file

Keywords: C# Lambda calculator Programming Attribute

Added by Slippy on Sun, 07 Jun 2020 12:04:04 +0300