C# Lambda Expressions

A lambda expression is a short, anonymous function you write inline — without giving it a name or a separate method block. Lambdas make your code shorter and more readable, especially when working with collections, events, and delegates.

The => Arrow Operator

Lambdas use the => symbol, which reads as "goes to" or "returns." The left side lists parameters; the right side is the expression or body.

// Regular method:
int Square(int x)
{
    return x * x;
}

// Equivalent lambda:
x => x * x

Lambda Anatomy Diagram

┌────────────────────────────────────────────────────────────┐
│         LAMBDA EXPRESSION ANATOMY                          │
├────────────────────────────────────────────────────────────┤
│                                                            │
│         x    =>    x * x                                   │
│         │    │     │                                       │
│         │    │     └── expression (the result)             │
│         │    └──── "goes to" operator                      │
│         └── parameter                                      │
│                                                            │
│   Multiple parameters:                                     │
│         (x, y)  =>  x + y                                  │
│                                                            │
│   No parameters:                                           │
│         ()  =>  Console.WriteLine("Hello")                 │
│                                                            │
│   Block body:                                              │
│         x  =>  { int result = x * 2; return result; }      │
│                                                            │
└────────────────────────────────────────────────────────────┘

Lambdas With Func and Action

Lambdas are commonly stored in Func<> and Action<> delegate types.

Func — returns a value

// Func<input, output>
Func<int, int> square = x => x * x;
Console.WriteLine(square(5));   // 25

Func<int, int, int> add = (a, b) => a + b;
Console.WriteLine(add(3, 4));   // 7

Func<string, string> greet = name => "Hello, " + name;
Console.WriteLine(greet("Alice"));  // Hello, Alice

Action — no return value

// Action<input>
Action<string> print = msg => Console.WriteLine(msg);
print("Learning C#!");   // Learning C#!

Action<int, int> showSum = (a, b) => Console.WriteLine("Sum: " + (a + b));
showSum(10, 5);   // Sum: 15

Lambdas with List Methods

Lambdas shine when used with collection methods like Find, FindAll, Where, Select, and Sort.

Find and Filter

List<int> numbers = new List<int>() { 3, 15, 7, 22, 10, 4 };

// Find first number greater than 10:
int first = numbers.Find(n => n > 10);
Console.WriteLine(first);  // 15

// Find all numbers greater than 10:
List<int> big = numbers.FindAll(n => n > 10);
// big = [15, 22]

// Remove all even numbers:
numbers.RemoveAll(n => n % 2 == 0);
// numbers = [3, 15, 7]

Sort with Custom Logic

List<string> names = new List<string>() { "Carol", "Alice", "Bob" };

// Sort by length of name:
names.Sort((a, b) => a.Length.CompareTo(b.Length));
// [Bob, Alice, Carol]

// Sort alphabetically:
names.Sort((a, b) => string.Compare(a, b));
// [Alice, Bob, Carol]

ForEach

List<int> scores = new List<int>() { 80, 90, 70 };

scores.ForEach(s => Console.WriteLine("Score: " + s));
// Score: 80
// Score: 90
// Score: 70

Lambdas in LINQ

Lambdas are the backbone of LINQ (Language Integrated Query). They let you filter, sort, and transform data in a readable style.

using System.Linq;

List<int> data = new List<int>() { 5, 12, 3, 8, 20, 1, 17 };

// Where = filter
var evens = data.Where(n => n % 2 == 0);
// [12, 8, 20]

// Select = transform
var doubled = data.Select(n => n * 2);
// [10, 24, 6, 16, 40, 2, 34]

// OrderBy = sort
var sorted = data.OrderBy(n => n);
// [1, 3, 5, 8, 12, 17, 20]

// Chained:
var result = data
    .Where(n => n > 5)
    .OrderBy(n => n)
    .Select(n => n * 10);
// [80, 120, 170, 200]

Block Body Lambdas

When your lambda needs more than one statement, use curly braces and a return keyword.

Func<int, string> classify = n =>
{
    if (n < 0) return "Negative";
    if (n == 0) return "Zero";
    return "Positive";
};

Console.WriteLine(classify(-5));  // Negative
Console.WriteLine(classify(0));   // Zero
Console.WriteLine(classify(7));   // Positive

Capturing Variables — Closures

A lambda can capture and use variables from the surrounding scope. This is called a closure.

int multiplier = 3;
Func<int, int> times = x => x * multiplier;

Console.WriteLine(times(4));  // 12
Console.WriteLine(times(7));  // 21

multiplier = 5;  // change the captured variable
Console.WriteLine(times(4));  // 20  ← uses new value!

Closure Diagram

┌────────────────────────────────────────────────────────────┐
│  int multiplier = 3;                                       │
│  Func<int,int> times = x => x * multiplier;                │
│                                    ↑                       │
│                              captures outer variable       │
│                                                            │
│  Lambda "remembers" multiplier even when called later      │
└────────────────────────────────────────────────────────────┘

Lambda vs Regular Method

┌──────────────────────────────┬───────────────────────────────┐
│ Regular Method               │ Lambda                        │
├──────────────────────────────┼───────────────────────────────┤
│ Has a name                   │ Anonymous (no name)           │
├──────────────────────────────┼───────────────────────────────┤
│ Defined separately           │ Written inline                │
├──────────────────────────────┼───────────────────────────────┤
│ Reusable across the program  │ Typically used once           │
├──────────────────────────────┼───────────────────────────────┤
│ Better for complex logic     │ Better for short operations   │
└──────────────────────────────┴───────────────────────────────┘

Quick Reference

┌────────────────────────────────────────────────────────────┐
│  Basic lambda:      x => x * x                             │
│  Two params:        (a, b) => a + b                        │
│  No params:         () => Console.WriteLine("Hi")          │
│  Block body:        x => { ...; return value; }            │
│  Func (returns):    Func<int, int> f = x => x + 1;         │
│  Action (no return):Action<string> a = s => Print(s);      │
└────────────────────────────────────────────────────────────┘

Lambda expressions make code dramatically more concise. Once you are comfortable reading the => arrow, you will find lambdas everywhere in C# — in LINQ queries, event handlers, sorting, filtering, and any place where a short function is needed without the overhead of a full method declaration.

Leave a Comment

Your email address will not be published. Required fields are marked *