In this post, I will write about

Delegates

Anonymous functions (Anonymous methods & Lambda expressions)

Built-in delegates (Func & Action delegates)

Let’s start with what a delegate is.

Delegates

A delegate is a type that represents references to methods with a particular parameter list and return type.

Delegates allow methods to be passed as parameters.

Delegate is a reference type and it holds the reference of a method.

All delegates implicitly derive from System.Delegate class.

class. C# handles callback functions and event handlers by delegates.

When you instantiate a delegate, you can associate its instance with any method with a compatible signature and return type. You can invoke (or call) the method through the delegate instance.

Here is an example that shows how to declare and instantiate a delegate:

Output:

Multicast delegate

A delegate that points to multiple methods is called a multicast delegate. The + operator adds a function to the delegate object and the - operator removes an existing function from a delegate object.

When the multicast delegate is called, it invokes the delegates in the list, in order. Only delegates of the same type can be combined.

Below is an example of multicast delegate usage:

Output:

The Evolution of Delegates in C#

In C# 1.0, you created an instance of a delegate by explicitly initializing it with a method that was defined elsewhere in the code.

C# 2.0 introduced the concept of anonymous methods as a way to write unnamed inline statement blocks that can be executed in a delegate invocation.

C# 3.0 introduced lambda expressions, which are similar in concept to anonymous methods but more expressive and concise.

These two features are known collectively as anonymous functions.

In general, applications that target version 3.5 and later of the .NET Framework should use lambda expressions.

Anonymous Method

An anonymous method is a method without a name. Anonymous methods in C# can be defined using the delegate keyword and can be assigned to a variable of delegate type.

An anonymous method

can access outer variables or functions.

can be passed as a parameter

can be used as event handler.

By using anonymous methods, you reduce the coding overhead in instantiating delegates because you do not have to create a separate method.

Below is an example that shows the anonymous method version of the delegate example we used above:

Lambda Expressions

A lambda expression is a block of code (an expression or a statement block) that is treated as an object. It can be passed as an argument to methods, and it can also be returned by method calls.

Lambda expression is a shorter way of representing anonymous methods.

A lambda expression uses => , the lambda declaration operator, to separate the lambda's parameter list from its executable code. To create a lambda expression, you specify input parameters (if any) on the left side of the lambda operator, and you put the expression or statement block on the other side.

Below is the lambda expression version of the code we used in the first delegate example:

For the above example, we can omit the curly brackets as there is only one statement and we can exclude the parameter types as well. Below is the concise version:

ArithmeticOperation sum = (number1, number2) =>

Console.WriteLine($"{number1} + {number2} = {number1 + number2}");

There can be lambda expressions without any parameters and we can use local variables in the lambda expressions as shown in the below example:

Output:

Lambda expressions can be used in LINQ queries as well:

Output:

Lambda expressions can be assigned to Func or Action delegates. We will examine these in the next section.

Action and Func Delegates

C# 3.0 introduced built-in generic delegate types Func and Action so that we don't have to declare custom delegates. These are included in the System namespace.

Action Delegate

Action in C# represents a delegate that has void return type and optional parameters.

An Action delegate can take up to 16 input parameters of different types.

In our delegate example we declared the delegate as below:

delegate void ArithmeticOperation(double operand1, double operand2);

If we use an Action delegate we do not need this declaration and we can directly make the assignment as below:

Action<double,double> sum = Addition;

As you see, parameter types must be the same.

So our code becomes the following:

An anonymous method can be assigned to Action delegate as below:

A lambda expression can also be used with Action delegate as below:

If you compare the first version and the last version, you can see that the code becomes more concise when we use Action delegate and lambda expression: