SoFunction
Updated on 2025-03-08

Detailed explanation of C# delegation and anonymous delegation

I originally wanted to write an article "The Past and Present Life of Lambda Expressions", but only the commission part has written a lot of content, so let's write it separately about the content of Lambda Expressions.

I don’t know who invented the Lambda expression. I only remember that the first time I came into contact with Lambda expression was when I used VS2008, so I think it was invented by Microsoft first.

Lambda expressions have become more and more popular since I came into contact with them. They have started to support them in Java 8, and kotlin has made extensive plagiarism about C# and F# (didn't C# treat Java like this at the time). In fact, this fully demonstrates the importance of Lambda expressions. To figure out Lambda, you need to figure out the delegation first.

Entrustment:

Suppose we are now going to develop a program that processes two integers (assuming that we process the addition operation first)

public class Worker
    {
      /// <summary>
      /// Process 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 b = (());

      Worker worker = new Worker();
      int result = (a, b);
      (("Result:{0}", result));

      string p = ();
}

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

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

Although there is a small change in a+b to a-b, it may face multiple changes here in the future (from subtraction to division......). If there is any change, change should be encapsulated. Here we can abstract the operation behaviors of a and b. What abstraction should we use? Entrustment

public class Worker
    {
      public delegate int TwoNumberHandleMethodDelegate(int x, int y);
      public int HandleTwoNumber(int a,int b)
      {
        return a + b;
      }
    }

public delegate int TwoNumberHandleMethodDelegate(int x, int y); Here is annotated with delegate, indicating that this is a delegate definition. If you remove delegate and observe the definition, you will find that this is an abstract method without a method body. Therefore, the meaning of delegation is: the type of method that is the same as the abstract method signature form. Delegation is a new data type you define. It is the same as int and class. Both are data types. int represents an integer, and as long as it is an integer, it can be assigned to an int-type variable; TwoNumberHandleMethodDelegate means that methods that receive two int-type parameters and return int-type results, so methods that meet the above requirements can be assigned to a variable of type TwoNumberHandleMethodDelegate.

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);
      }
    }

In this way, the operations of a and b are encapsulated, and all changes are left to the caller to handle. The meaning here: HandleTwoNumber handles two integers a and b. The specific processing is implemented by handle. At this time, you may ask, how to 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 b = (());
       method = new (Add);
      Worker worker = new Worker();
      int result = (10, 10,method);
 //int result = (10, 10, Sub);//Simplified version      (("Result:{0}", result));
 }

According to the above program, we can see that the Main code block is the caller of the worker. As the caller, you should be the clearest about the work you want the worker to do. Therefore, as the callee's worker, it only needs to receive the a\b parameters given by the caller Main and execute the algorithm method customized by Main, and then execute it according to the algorithm and return the result. Although the above code is simple, it has far-reaching significance. As programming time increases, I believe your understanding will become deeper.

In addition to the standard way of assigning delegate variables, they can also be simplified:

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

The compiler will automatically check whether Add complies with the definition of TwoNumberHandleMethodDelegate. If it is in compliance, you allow the method name to be assigned to the delegate variable directly.

Anonymous commission

Through the above example code, it is easy to find that the TwoNumberHandleMethodDelegate method variable is assigned to Add(Sub), so when calling method(...) is equivalent to calling Add(......). In this way, you can think

method is completely equivalent to Add. Since it is equivalent, can we directly assign the definition content of Add to the method variable? The answer is yes:

static void Main(string[] args)
    {

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

But it is not possible to use a hard-pull like the above, you still need to make modifications. The modification content is: because the current code is in the Main method, the access modifier is 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 to be assigned must meet the requirements of the return type int, and all ints will be removed at this time; because after assignment, method is equivalent to Add, and invocation can be completed by the method variable in the future, and all Add method names do not need to be removed. This code becomes the following form:

static void Main(string[] args)
    {

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

The above modification has been simplified a lot, but what is the right end of the method assigned =? At this time, the compiler cannot correctly recognize this method, because the definition of the method needs to meet five parts: access to amulet, return type, method name, parameter list, and method body. Although you know in your heart that this is a simplified method, the compiler does not understand your heart..., that doesn't matter, just tell the compiler that the next one is a simplified method.

static void Main(string[] args)
    {

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

As you expected, now the compiler knows that = on the right is your simplified method; ok, you can now assign and use it normally.

Through the above definition, we found that the simplified method marked with delegate does not have a fixed name like Add/Sub. Therefore, we call this method anonymous delegation (I am used to calling it anonymous method).

You may also notice that the anonymous delegation is assigned to the local variable method in the Main code quickly after it is defined, so when the scope of the method is exceeded, the method will never have a chance to call it again. This leads to the most common usage of anonymous methods, anonymous delegates, and anonymous functions, which are used to define functional codes that only need to be used once.

The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.