Learn how to use lambda expressions in C#. This tutorial covers lambda syntax, anonymous functions, functional programming concepts, and practical examples for using lambda in .NET applications.
last modified May 14, 2025
This C# lambda expression tutorial explains how to use lambda expressions to write more concise and readable code in C#.
A lambda expression is an anonymous function that is not bound to an identifier. It can be used wherever a delegate type is expected, allowing for in-line function definitions without explicitly declaring a separate method. Lambda expressions are commonly used in LINQ queries, event handling, and functional programming.
Lambda expressions enable a more compact syntax compared to traditional methods, improving code readability and reducing boilerplate. They are especially useful for short operations where defining a full method would be unnecessary.
Lambda expressions have two primary forms:
Syntax
Description
(input-parameters) => expression
Single-line lambda with an expression body.
(input-parameters) => { <sequence-of-statements> }
Multi-line lambda with a statement block.
The following is a simple example with lambda expressions.
Program.cs
Func<int, int> square = x => x * x; Func<int, int> cube = x => x * x * x; Func<int, int> inc = x => x++; Func<int, int, int> add = (x, y) => x + y;
Console.WriteLine(square(5)); Console.WriteLine(cube(5)); Console.WriteLine(inc(5)); Console.WriteLine(add(5, 7));
In the example, we define four functions.
Func<int, int> square = x => x * x;
A Func delegate refers to a lambda expression, which squares the input value. This is the closest equivalent of plain functions in other languages.
$ dotnet run 25 125 5 12
The lambda statement may have multiple statements, which are enclosed in {} braces.
Program.cs
Action<string> greet = name => { string greeting = $“Hello {name}!”; Console.WriteLine(greeting); };
greet(“Pau”); greet(“Lucia”);
In the example, we use an Action delegate. On the right side of the equation, we have a lambda statement, which consists of two statements. The Action delegate takes one input parameter and does not return anything.
$ dotnet run Hello Pau! Hello Lucia!
In the following examples, we work with arrays.
Program.cs
int[] vals = [1, -2, 3, 4, 0, -3, 2, 1, 3];
var v1 = Array.FindIndex(vals, x => x == 3); Console.WriteLine(v1);
var v2 = Array.FindLastIndex(vals, x => x == 3); Console.WriteLine(v2);
var positive = Array.FindAll(vals, x => x > 0); Console.WriteLine(string.Join(",", positive));
The array functions expect a predicate function, which is applied for all elements of the array.
var positive = Array.FindAll(vals, x => x > 0);
We pass the FindAll method a lambda expressions as its second parameter; the expression is a predicate which returns true for values greater than zero.
$ dotnet run 2 8 1,3,4,2,1,3
We can use lambda expressions in many LINQ methods.
Program.cs
List<int> vals = [-1, 2, -2, 0, 3, 4, -5];
var squared = vals.Select(x => x * x); Console.WriteLine(string.Join(", “, squared));
var filtered = vals.Where(x => x > 0); Console.WriteLine(string.Join(”, “, filtered));
In the example, we use lambda expression in LINQ’s Select and Where methods.
$ dotnet run 1, 4, 4, 0, 9, 16, 25 2, 3, 4
Since C# 12, parameters in lambdas can have default values.
Program.cs
var message = (string greet, string name = “there”) => $"{greet} {name}!”;
var res = message(“Hi”, “Tom”); Console.WriteLine(res);
var res2 = message(“Hello”); Console.WriteLine(res2);
Providing the name parameter becomes now optional. The optional parameters must follow the mandatory.
$ dotnet run Hi Tom! Hello there!
In the following example, we create an array of lambda expressions.
Program.cs
Func<int, int>[] funs = [ x => x * x, x => ++x, x => –x ];
for (int i = 0; i < 6; i++) { Console.WriteLine(funs0); Console.WriteLine(funs1); Console.WriteLine(funs2); Console.WriteLine(); }
In the example, we put three lambda expression in an array. Then in the for loop, we pass integers 0..5 to the three lambda expressions.
Since C# 9.0, we can use discards (_) as parameters of lambdas and anonymous methods.
Program.cs
using System.Windows.Forms; using System.Drawing;
namespace QuitButton;
class MyForm : Form { private FlowLayoutPanel flowPanel = new();
public MyForm()
{
InitComponents();
}
private void InitComponents()
{
Text = "Quit button";
ClientSize = new Size(800, 450);
flowPanel = new FlowLayoutPanel();
flowPanel.Dock = DockStyle.Fill;
flowPanel.BorderStyle = BorderStyle.FixedSingle;
var button = new Button();
button.Margin = new Padding(10, 10, 0, 0);
button.Text = "Quit";
button.AutoSize = true;
button.Click += (_, _) => Close();
flowPanel.Controls.Add(button);
Controls.Add(flowPanel);
CenterToScreen();
}
[STAThread]
static void Main()
{
Application.SetHighDpiMode(HighDpiMode.SystemAware);
Application.EnableVisualStyles();
Application.Run(new MyForm());
}
}
The example is a simple GUI application created with Winforms; it works only on Windows.
button.Click += (_, _) => Close();
Since we do not work with the sender object and the event arguments, we can use discards.
A lambda expression can capture and use variables from its enclosing scope. This is called a closure.
Program.cs
int factor = 3; Func<int, int> multiply = x => x * factor;
Console.WriteLine(multiply(5)); factor = 4; Console.WriteLine(multiply(5));
The lambda expression uses the variable factor from the outer scope. If the value of factor changes, the lambda reflects the new value.
Lambdas can be used to define custom sort orders for collections, such as sorting strings by length.
Program.cs
List<string> words = [“pear”, “apple”, “banana”, “kiwi”];
words.Sort((a, b) => a.Length.CompareTo(b.Length)); Console.WriteLine(string.Join(", “, words));
The lambda (a, b) => a.Length.CompareTo(b.Length) is used as a custom comparator to sort the list by string length.
A lambda can have multiple parameters and a block of statements, such as for aggregating values.
Program.cs
List<int> nums = [1, 2, 3, 4];
int sum = nums.Aggregate(0, (acc, x) => {
int result = acc + x;
Console.WriteLine($"Adding {x}, sum so far: {result}");
return result;
});
Console.WriteLine($“Total: {sum}”);
This example uses a multi-parameter, multi-statement lambda in Aggregate to sum values and print progress at each step.
In this article we have worked with lambda expressions in C#.
Lambda expressions and anonymous functions
My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.
List all C# tutorials.