C# -

Lambda Expressions

Lambda expressions in C# provide a concise way to represent anonymous methods using special syntax. They are used extensively in LINQ and other places where short snippets of code are required. This tutorial covers what lambda expressions are, how to use them, and provides a detailed explanation of their internal workings with an equivalent method representation.


1. Understanding Lambda Expressions

Lambda expressions are a shorthand syntax for writing anonymous methods. They are particularly useful for writing inline code that can be passed as arguments to methods.

Syntax:

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


2. Basic Example

Let's start with a simple example of using a lambda expression to square a number.

Lambda Expression:
        
            namespace LambdaExamples;

class Program
{
    static void Main(string[] args)
    {
        // Lambda expression to square a number
        Func<int, int> square = x => x * x;
        int result = square(5);
        Console.WriteLine(result); // Output: 25
    }
}
        
    
Equivalent Method:
        
            namespace LambdaExamples;

class Program
{
    static void Main(string[] args)
    {
        // Equivalent method to square a number
        int result = Square(5);
        Console.WriteLine(result); // Output: 25
    }

    static int Square(int x)
    {
        return x * x;
    }
}
        
    

3. Using Lambda Expressions with LINQ

Lambda expressions are often used with LINQ to perform operations like filtering, selecting, and transforming data.

Example:
        
            using System;
using System.Collections.Generic;
using System.Linq;

namespace LambdaExamples;

class Program
{
    static void Main(string[] args)
    {
        List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6 };

        // Using lambda expression with LINQ to filter even numbers
        var evenNumbers = numbers.Where(n => n % 2 == 0);

        foreach (var number in evenNumbers)
        {
            Console.WriteLine(number); // Output: 2, 4, 6
        }
    }
}
        
    
Equivalent Method:
        
            using System;
using System.Collections.Generic;
using System.Linq;

namespace LambdaExamples;

class Program
{
    static void Main(string[] args)
    {
        List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6 };

        // Using a method to filter even numbers
        var evenNumbers = numbers.Where(IsEven);

        foreach (var number in evenNumbers)
        {
            Console.WriteLine(number); // Output: 2, 4, 6
        }
    }

    static bool IsEven(int n)
    {
        return n % 2 == 0;
    }
}
        
    

4. Custom Where Method

Let's implement a custom `Where` method to demonstrate how lambda expressions work behind the scenes.

Custom Where Method:
        
            using System;
using System.Collections.Generic;

namespace LambdaExamples;

public static class EnumerableExtensions
{
    public static IEnumerable<T> CustomWhere<T>(this IEnumerable<T> source, Func<T, bool> predicate)
    {
        foreach (var item in source)
        {
            if (predicate(item))
            {
                yield return item;
            }
        }
    }
}
        
    
Using Custom Where Method:
        
            using System;
using System.Collections.Generic;

namespace LambdaExamples;

class Program
{
    static void Main(string[] args)
    {
        List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6 };

        // Using custom Where method to filter even numbers
        var evenNumbers = numbers.CustomWhere(n => n % 2 == 0);

        foreach (var number in evenNumbers)
        {
            Console.WriteLine(number); // Output: 2, 4, 6
        }
    }
}
        
    

5. Built-in Lambda Methods

Here is a table of some commonly used built-in lambda methods in C#:

Method Description Example
Where Filters a sequence of values based on a predicate. var evens = numbers.Where(n => n % 2 == 0);
Select Projects each element of a sequence into a new form. var squares = numbers.Select(n => n * n);
FirstOrDefault Returns the first element of a sequence, or a default value if no element is found. var first = numbers.FirstOrDefault(n => n > 10);
OrderBy Sorts the elements of a sequence in ascending order. var sorted = numbers.OrderBy(n => n);
GroupBy Groups the elements of a sequence according to a specified key selector function. var grouped = numbers.GroupBy(n => n % 2);
Aggregate Applies an accumulator function over a sequence. var sum = numbers.Aggregate((a, b) => a + b);

6. Additional Examples

Let's look at some more examples of lambda expressions in action.

Sorting with Lambda Expressions:
        
            using System;
using System.Collections.Generic;
using System.Linq;

namespace LambdaExamples;

class Program
{
    static void Main(string[] args)
    {
        List<int> numbers = new List<int> { 3, 1, 4, 1, 5, 9 };

        // Using lambda expression to sort numbers in ascending order
        var sortedNumbers = numbers.OrderBy(n => n);

        Console.WriteLine("Sorted Numbers:");
        foreach (var number in sortedNumbers)
        {
            Console.WriteLine(number); // Output: 1, 1, 3, 4, 5, 9
        }
    }
}
        
    
Finding Maximum Value:
        
            using System;
using System.Collections.Generic;
using System.Linq;

namespace LambdaExamples;

class Program
{
    static void Main(string[] args)
    {
        List<int> numbers = new List<int> { 3, 1, 4, 1, 5, 9 };

        // Using lambda expression to find the maximum value
        int maxNumber = numbers.Max();

        Console.WriteLine($"Maximum Number: {maxNumber}"); // Output: Maximum Number: 9
    }
}
        
    
Calculating Sum:
        
            using System;
using System.Collections.Generic;
using System.Linq;

namespace LambdaExamples;

class Program
{
    static void Main(string[] args)
    {
        List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };

        // Using lambda expression to calculate the sum of numbers
        int sum = numbers.Sum();

        Console.WriteLine($"Sum: {sum}"); // Output: Sum: 15
    }
}
        
    
Grouping Elements:
        
            using System;
using System.Collections.Generic;
using System.Linq;

namespace LambdaExamples;

class Program
{
    static void Main(string[] args)
    {
        List<string> words = new List<string> { "apple", "banana", "cherry", "date", "elderberry", "fig", "grape" };

        // Using lambda expression to group words by their first letter
        var groupedWords = words.GroupBy(word => word[0]);

        Console.WriteLine("Grouped Words:");
        foreach (var group in groupedWords)
        {
            Console.WriteLine($"Group {group.Key}:");
            foreach (var word in group)
            {
                Console.WriteLine($"  {word}");
            }
        }
    }
}
        
    


Conclusion

Lambda expressions provide a powerful and concise way to write inline code, making it easier to work with collections and perform operations. By understanding how they are translated into methods, you can better appreciate their efficiency and utility.