C#

Lambda Expressions in C#

In this article, we’re going to learn what Lambda Expressions in C# are in detail.

To download the source code for this article, you can visit our GitHub repository.

Let’s begin.

What Are Lambda Expressions?

Lambda expressions were first introduced in C# 3 in 2007. Since then, Lambda expressions have helped us simplify and minimize the verbosity of our codebase, undoubtedly.

Lambda expressions are simply anonymous/delegate functions, but with a simple and expressive syntax.

We can assign the lambda expression to a variable, pass it as a parameter or specify it as a property.

Usage of Lambda Expressions

Let’s see some of the most common usages of lambda expressions.

Language Integrated Query (LINQ)

LINQ heavily uses lambda expressions:

var fruits = new[] { "apple", "orange", "mango", "pineapple" };

var fruitsOrdered = fruits.OrderBy(name => name).ToArray();
var fruitsUpperCase = Fruits.Select(name => name.ToUpper()).ToArray();
var mango = Fruits.First(name => name == "mango");

Here, name => name, name => name.ToUpper(), name => name == mango are the lambda expressions (in form of delegates) passed to OrderBy, Select, First methods respectively.

Minimal API

In ASP.NET Core 6, Minimal APIs are introduced.

A simple GET API that returns “Hello World!”:

var app = WebApplication.Create(args);
app.MapGet("/", () => "Hello World!");
app.Run();

Here, () => "Hello World!" is the lambda expression passed as the second parameter to MapGet method.

Events

Lambda expressions can be used to subscribe to events as long as they share the same method signature of the event’s delegate type. In our case, EventHandler is a built-in delegate type. Now, we know events, delegates, and lambda expressions are closely related to each other:

public event EventHandler Event;

Lambda expression subscribing to the event:

Event += (obj, eventArgs) =>
{
    Console.WriteLine("Event raised!");
};

Syntax of Lambda Expressions

The syntax of lambda expressions contains parameters on the left side, and expressions or statements on the right side (body), separated by the => operator.

Expression Lambda

Expression lambda contains the single expression in the lambda body:

(<parameters>) => expression

A sample for expression lambda with return value:

var sum = () => 1 + 1;

Another one, without any return value:

var sayHello = () => Console.WriteLine("Hello");

Another sample, accepting parameters and no return value:

var sayName = (string name) => Console.WriteLine($"Hello {name}");
//or
Action<string> sayName = name => Console.WriteLine($"Hello {name}");

var sayFullName = (string firstName, string lastName) => Console.WriteLine($"Hello {firstName} {lastName}");

Note: The parentheses () are not required for a single parameter. But, it applies only to explicitly declared target types. However,  it is mandatory when there is more than one parameter.

Statement Lambda

Statement lambdas enclose one or more statements in the lambda body with curly braces {}:

(<parameters>) => { <statements> }

Sample of statement lambda with parameters and return type:

var sum = (int a, int b) =>
{
    var sum = a + b;
    return sum;
}

Executing Lambda Expressions:

Lambda expressions assigned to variables, parameters, or properties will hold only the reference to the lambda expressions. Hence, we don’t execute lambdas at the time of assigning. Whenever needed, we can execute like methods:

sum();
sayHello();
sayName("Code Maze");
sayFullName("Code", "Maze");
sum(1, 1);

Async/Await With Lambda Expressions

Likewise the regular methods, we can use async, await keywords in the lambda expressions to take advantage of asynchronous operations.

For instance, let us look at a simple async expression lambda which will wait for 1000 milliseconds:

var lambda = async () => await Task.Delay(1000);
 
await lambda();

Similarly, for statement lambda:

var lambda = async () =>
{
    await Task.Delay(1000);
    Console.WriteLine("Completed async task");
};
 
await lambda();

Lambda Expression Type

In general, Lambda expressions do not have any type. However, we can assign them to the Action or Func delegate type based on the parameter and return type.

Before C# 10, we need to specify the type explicitly while assigning variables:

Action sayHello = () => Console.WriteLine("Hello!");
Action<string> sayName = (name) => Console.WriteLine($"Hello {name}");
 
Func<int> sum = () => 1 + 1;
Func<int, int> square = (number) => number * 2;

From C# 10 onward, the compiler will naturally infer the type of variable as Action or Func delegate:

var sayHello = () => Console.WriteLine("Hello!");
var sayName = (string name) => Console.WriteLine($"Hello {name}");

var sum = () => 1 + 1;
var square = (int number) => number * 2;

Note: Whenever we use var keyword to declare the lambda expression, we need to specify the parameter type explicitly.

In this example, If we infer the type of sayHello variable in Visual Studio, it will show Action?.  Similarly for other variables sayName, sum, square , the type is inferred as Action<string>, Func<int>, Func<int, int>.

To learn more about Func and Action delegate types, please refer to the C# delegates article.

Return Type of Lambda Expression

Generally, the compiler infers the return type from the lambda expression body’s expression or statements. But, in rare cases, we may need to specify the return type explicitly:

Func<int, object?> returnNullOrNumber = object? (number) =>
{
    return number > 0 ? number : null;
};

In the above example, the return type is object?. Because we return two different values int and null.

Conclusion

In this article, we have learned about Lambda expressions and their usage through various examples.

Code Maze

Share
Published by
Code Maze

Recent Posts

Code Maze Weekly #134

Issue #134 of the Code Maze weekly. Check out what's new this week and enjoy…

Updated Date Aug 12, 2022

Heap Sort in C#

In this article, we'll look at the heap sort algorithm in C#. We'll discuss what…

Updated Date Aug 11, 2022

Flags Attribute For Enum in C#

In this article, we are going to learn about the Flags attribute for enum in…

Aug 10, 2022

Code Maze Weekly #133

Issue #133 of the Code Maze weekly. Check out what's new this week and enjoy…

Updated Date Aug 5, 2022

Type Checking and Type Casting in C#

In this article, we are going to learn various ways of converting a value from…

Updated Date Aug 5, 2022

Sort Dictionary by Value in .NET

In this article, we are going to learn how to sort the values in the…

Updated Date Aug 4, 2022