Search⌘ K
AI Features

Lambdas

Explore how to use lambda expressions in C# as a concise way to represent anonymous methods within delegates and events. Understand their syntax, including parameters, return values, and passing lambdas as method arguments. Gain clarity on why lambdas are preferred over anonymous methods for modern C# programming.

Lambda expressions (or simply “lambdas”) are a concise way to represent anonymous methods. They allow us to write code that is shorter and often more readable than using the delegate keyword.

Creating a delegate with a lambda

Let’s rewrite the example from the previous lesson using a lambda expression.

C# 14.0
// Lambda expression defined with the => operator
MathOperation mathOperation = (operand1, operand2) => operand1 + operand2;
// We can add another lambda to the invocation list
mathOperation += (x, y) => x - y;
Console.WriteLine(mathOperation(2, 3));
delegate int MathOperation(int operand1, int operand2);
  • Line 2: We define a lambda expression (operand1, operand2) => operand1 + operand2. The compiler infers that operand1 and operand2 are integers based on the MathOperation delegate definition.

  • Line 5: We add a second lambda (x, y) => x - y to the delegate instance.

  • Line 7: We invoke the delegate. As with anonymous methods, mathOperation returns the result of the last method in the list (2 - 3 = -1).

Syntax and usage

A lambda expression has two main parts, separated by the lambda operator => (read as “goes to”):

  1. Input parameters on the left (if any).

  2. Expression or statement block on the right.

In an expression lambda, like the one shown above, we omit the return keyword because the expression automatically returns its result.

Single parameter syntax

If a lambda expression has exactly one parameter, we can omit the parentheses around the parameter name.

C# 14.0
// Parentheses are optional for a single parameter
IncrementOperation incrementor = x => x + 1;
Console.WriteLine(incrementor(5));
delegate int IncrementOperation(int number);
  • Line 2: We define the lambda x => x + 1. The compiler infers x is an int. Since there is only one parameter, we omit the parentheses ().

  • Line 4: We invoke the delegate with 5, returning 6.

No parameters and no return value

If the lambda takes no parameters, we must use empty parentheses ().

C# 14.0
// Empty parentheses are required when there are no parameters
MessagePrinter printer = () => Console.WriteLine("Hello World!");
printer += () => Console.WriteLine("Hello once again!");
printer();
delegate void MessagePrinter();
  • Line 5: We use () to indicate zero parameters.

  • Line 5: The body is a single statement (Console.WriteLine). Since the delegate returns void, this is a valid expression lambda.

  • Line 9: We invoke the delegate, executing both lambdas in order.

Explicit parameter types

The compiler usually infers parameter types automatically. However, if a delegate uses ref or out parameters, we must specify the types explicitly in the lambda.

C# 14.0
// We must specify the type for ref parameters
IncrementOperation incrementor = (ref int number) => number++;
int x = 10;
incrementor(ref x);
Console.WriteLine(x);
// Delegate with a ref parameter
delegate void IncrementOperation(ref int number);
  • Line 2: We define a lambda that accepts a ref int. The body number++ increments the value.

  • Line 5: We pass x by reference. The lambda modifies the original variable.

Lambdas as method parameters

Just like anonymous methods, lambdas are frequently used as arguments for methods that accept delegates. This allows us to pass behavior, such as a calculation or specific action, directly into a method.

C# 14.0
int x = 10;
// Pass a lambda expression directly as the second argument
ModifyNumber(ref x, (ref int number) => number++);
Console.WriteLine(x);
// This method accepts a delegate as a parameter
void ModifyNumber(ref int number, IncrementOperation incrementor)
{
incrementor(ref number);
}
delegate void IncrementOperation(ref int number);
  • Line 4: We call ModifyNumber. The second argument is a lambda expression (ref int number) => number++.

  • Line 9: The ModifyNumber method takes an IncrementOperation delegate, which matches the signature of our lambda.

  • Line 11: The method invokes the delegate, executing the logic defined in our lambda.

Lambdas vs. anonymous methods

While both features allow us to create inline methods, lambda expressions are the preferred modern syntax.

Feature

Lambda expression

Anonymous method

Syntax

Concise (=>)

Verbose (delegate)

Type inference

Implicit types (usually)

Explicit types (usually)

Parameter list

Required (except single param)

Can be omitted entirely

Always use lambda expressions for new code. Use anonymous methods only when maintaining legacy code or if you specifically need to ignore all parameters using the delegate { } syntax.