Delegation and Anonymous Delegation

Keywords: C# Lambda Java Programming

Originally, I wanted to write an article "The Past and Present Life of Delegation and Lambda Expressions", but only the delegation part has written a lot of content, so I will separate the content of Lambda Expressions and write it later.

I don't know who invented the Lambda expression. Just remember that the first time I came into contact with the Lambda expression was when I used VS 2008. I think Microsoft invented it first.

Lambda expressions have become more and more popular since I came into contact with them. Java 8 supports them and kotlin copies C# and F# extensively (C# did not treat Java that way at any time). In fact, this fully illustrates the importance of Lambda expression. To clarify Lambda, we first need to clarify the delegation.

Entrust:

Let's assume that now we're going to develop a program that handles two integers (assuming that the addition operation is handled first)

public class Worker
        {
            /// <summary>
            /// Processing two numbers
            /// </summary>
            /// <param name="a"></param>
            /// <param name="b"></param>
            /// <returns></returns>
            public int HandleTwoNumber(int a,int b)
            {
                return a + b;
            }
        }
static void Main(string[] args)
        {
            int a = int.Parse(Console.ReadLine());
            int b = int.Parse(Console.ReadLine());

            Worker worker = new Worker();
            int result = worker.HandleTwoNumber(a, b);
            Console.WriteLine(String.Format("Result:{0}", result));

            string p = Console.ReadLine();
}

If, after a period of time, we need to change it to a subtraction operation:

public class Worker
        {
            public int HandleTwoNumber(int a,int b)
            {
                return a - b;
            }
        }

Although the change from a+b to a-b is very small, there may be many changes (from subtraction to division...) in the future. Change should be encapsulated if there is change. Here we can abstract the operation behavior of a and B. What abstraction can we use? Entrust

public class Worker
        {
            public delegate int TwoNumberHandleMethodDelegate(int x, int y);
            public int HandleTwoNumber(int a,int b)
            {
                return a + b;
            }
        }
Public delegate int TwoNumberHandle Method Delegate (int x, int y); this is marked with delegate to indicate that this is a delegate definition. If you remove delegate and look at the definition again, you will see that this is one.
There is no abstract method of method body. The meaning of all delegates is the same method type as the signature form of the abstract method. Delegation is a new data type that you define. It is the same data type as int and class. Int represents an integer, which can be assigned to as long as it is an integer
An int variable; TwoNumberHandleMethodDelegate means a method that receives two int parameters and returns an int result, so methods that satisfy the above requirements can be assigned to TwoNumberHandleMethodDelegate class variables.

In this way, the Worker code can be modified to:
public class Worker
        {
            public delegate int TwoNumberHandleMethodDelegate(int x, int y);
            public int HandleTwoNumber(int a, int b, TwoNumberHandleMethodDelegate handle)
            {
                return handle(a, b);
            }
        }

So the operations of a and B are encapsulated, and all changes are handled by the caller. Meaning here: Handle TwoNumber handles two integers a and b, and how to handle them is implemented by handle. At this point, you may ask, how do you call this method? The call is as follows:

private static int Add(int a, int b)
        {
            return a + b;
        }

        private static int Sub(int a, int b)
        {
            return a - b;
        }

        static void Main(string[] args)
        {
            int a = int.Parse(Console.ReadLine());
            int b = int.Parse(Console.ReadLine());
            Worker.TwoNumberHandleMethodDelegate method = new Worker.TwoNumberHandleMethodDelegate(Add);
            Worker worker = new Worker();
            int result = worker.HandleTwoNumber(10, 10,method);
       //
int result = worker.HandleTwoNumber(10, 10, Sub);//Simplified Edition
Console.WriteLine(String.Format("Result:{0}", result)); }

According to the above program, the main code block is the caller of the worker. As the caller, he should know what he wants woker to do best. Therefore, as the worker of the callee, it only needs to receive a given by the caller Main.\

b parameter and the algorithm to be executed, then execute according to the algorithm and return the result. Although the above code is simple, it has far-reaching significance. As the programming time increases, I believe that your understanding will be more profound.

In addition to the standard way, delegated variables can be simplified in assigning values:

Worker.TwoNumberHandleMethodDelegate method = new Worker.TwoNumberHandleMethodDelegate(Add);
            Worker worker = new Worker();
            int result = worker.HandleTwoNumber(10, 10,method);
//It can be simplified to
// int result = worker.HandleTwoNumber(10, 10,Add);

The compiler will automatically check whether Add complies with the definition of TwoNumberHandle Method Delegate, and assign method names directly to delegate variables if it complies.

anonymous delegate

From the example code above, it is easy to find that the TwoNumberHandleMethodDelegate method variable is assigned to Add(Sub), so when method(...) is called, it is relative to the call to Add(...). In this way, we can think of it as follows

Method and Add are completely equivalent. Since they are equivalent, can we assign the definition of Add directly to the method variable? The answer is yes:

static void Main(string[] args)
        {

            Worker.TwoNumberHandleMethodDelegate method =private static int Add(int a, int b)
        {
            return a + b;
        };
}

But it's impossible to pull the hard cover like the one above. You still need to make some modifications. The modification is as follows: because our code is now in the Main method, access modifiers should be removed, and static should also be removed; at the same time, the compiler knows that you want to assign a value to the method, then the value you want to assign must satisfy the requirement that the return type is int, and all ints are redundant at this time; because after assignment, the method is equivalent to Add, and later calls need the Add side. The method name is called, and all Adds need not be removed. So the code becomes as follows:

static void Main(string[] args)
        {

            Worker.TwoNumberHandleMethodDelegate method =   (int a, int b)
        {
            return a + b;
        };
}

It's simplified a lot after the above modification, but what's the right-hand side of the method assignment? At this time, the compiler can not correctly identify this method, because the definition of the method needs to satisfy five parts: access to the tattoo, return type, method name, parameter list, method body. Although you know in your mind that this is a simplified method, but the compiler does not understand your mind..., that's okay as long as we tell the compiler, the latter is a simplified method.

static void Main(string[] args)
        {

            Worker.TwoNumberHandleMethodDelegate method =   delegate(int a, int b)
        {
            return a + b;
        };
}

As you might expect, the compiler now knows that = on the right side is your simplified method; ok, you can now assign and use it properly.

Through the above definition, we find that there is no fixed name like Add/Sub in the simplified method of delegate annotation. So we call this method anonymous delegation (I'm used to calling it anonymous).

You may also notice that when the anonymous delegate is defined, it is assigned to the local variable method in the fast Main code, so when the access domain of the method exceeds, it has no chance to call it again. This leads to the most common uses of anonymous methods, anonymous delegates, and anonymous functions, which are used to define functional code that only needs to be used once.

Posted by Mr Tech on Fri, 31 May 2019 16:37:35 -0700