Delegates, Events & Lambdas in C#

Delegates, Events & Lambdas in C#

Delegates, Events & Lambdas in C# – A Practical Guide

1. What Are Delegates?

Delegates in C# are like function pointers in C++, but type-safe. A delegate is a reference type that holds the reference to a method. It can invoke any method that matches its signature. Delegates are the backbone of event handling and LINQ operations in C#.

1.1 Basic Delegate Declaration and Use

public delegate void DisplayMessage(string message);

class Program
{
    static void Show(string msg)
    {
        Console.WriteLine("Message: " + msg);
    }

    static void Main()
    {
        DisplayMessage del = Show;
        del("Hello, Delegates!");
    }
}

2. Multicast Delegates

A delegate can point to multiple methods. When invoked, all the methods are called in the order they were added.

public delegate void MultiDelegate();

class Program
{
    static void MethodA() => Console.WriteLine("Method A");
    static void MethodB() => Console.WriteLine("Method B");

    static void Main()
    {
        MultiDelegate del = MethodA;
        del += MethodB;
        del(); // Calls both MethodA and MethodB
    }
}

3. What Are Events in C#?

Events are a way to provide notifications. An event is a wrapper around a delegate. Only the class that defines the event can invoke it, but other classes can subscribe to it.

public class Alarm
{
    public event Action OnRing;

    public void Ring()
    {
        if (OnRing != null)
        {
            OnRing();
        }
    }
}

class Program
{
    static void Alert() => Console.WriteLine("Alarm ringing!");

    static void Main()
    {
        Alarm alarm = new Alarm();
        alarm.OnRing += Alert;
        alarm.Ring();
    }
}

4. Lambda Expressions

Lambdas are anonymous functions. They provide a short and expressive way to write methods directly inline.

Func<int, int, int> add = (a, b) => a + b;
Console.WriteLine(add(10, 5)); // Output: 15

5. Built-in Delegates: Action, Func, and Predicate

5.1 Action Delegate

Action represents a method that returns void. You can use it when you just want to perform an action without returning anything.

Action<string> greet = name => Console.WriteLine($"Hello, {name}!");
greet("Alice");

5.2 Func Delegate

Func returns a value. The last type parameter represents the return type.

Func<int, int, int> multiply = (x, y) => x * y;
Console.WriteLine(multiply(4, 5)); // Output: 20

5.3 Predicate Delegate

Predicate always returns a boolean value and takes one input parameter.

Predicate<int> isEven = num => num % 2 == 0;
Console.WriteLine(isEven(10)); // Output: True

6. Combining Delegates with Lambdas

Lambdas work beautifully with delegates, especially when you need to define behavior inline without creating separate method definitions. This is common in event handling and LINQ queries.

Action show = () => Console.WriteLine("This is a lambda with Action!");
show();

Or use lambdas in combination with your own delegates:

public delegate int Operation(int x, int y);

class Program
{
    static void Main()
    {
        Operation add = (a, b) => a + b;
        Operation sub = (a, b) => a - b;

        Console.WriteLine(add(10, 5)); // Output: 15
        Console.WriteLine(sub(10, 5)); // Output: 5
    }
}

7. Events with Custom EventArgs

For more informative event handling, you can define custom EventArgs to pass additional data when an event is raised.

public class TemperatureEventArgs : EventArgs
{
    public int CurrentTemp { get; set; }
}

public class Thermostat
{
    public event EventHandler<TemperatureEventArgs> TemperatureChanged;

    public void ChangeTemperature(int newTemp)
    {
        TemperatureChanged?.Invoke(this, new TemperatureEventArgs { CurrentTemp = newTemp });
    }
}

class Program
{
    static void Main()
    {
        Thermostat t = new Thermostat();
        t.TemperatureChanged += (sender, e) =>
        {
            Console.WriteLine("New Temperature: " + e.CurrentTemp);
        };
        t.ChangeTemperature(75);
    }
}

8. Real-World Example: Event-Driven Design

Let’s say you're building a file downloader app. You might want to notify the UI when the download completes. That’s where events and delegates come in.

public class FileDownloader
{
    public event Action DownloadComplete;

    public void StartDownload()
    {
        Console.WriteLine("Downloading...");
        Thread.Sleep(2000); // Simulate download
        DownloadComplete?.Invoke();
    }
}

class Program
{
    static void Main()
    {
        FileDownloader downloader = new FileDownloader();
        downloader.DownloadComplete += () => Console.WriteLine("Download finished!");
        downloader.StartDownload();
    }
}

This event-driven model makes your applications more modular, scalable, and responsive.

9. LINQ with Delegates and Lambdas

Lambdas and built-in delegates like Func and Predicate are central to LINQ in C#. Here’s an example of using them together in a LINQ query:

List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6 };

var evenNumbers = numbers.Where(n => n % 2 == 0);

foreach (var num in evenNumbers)
{
    Console.WriteLine(num);
}

This filters out only even numbers using a lambda passed to the Where method, which accepts a Func<int, bool> delegate.

10. Conclusion

Delegates, events, and lambdas are foundational to modern C# development. They offer a powerful way to decouple code, implement callbacks, handle events, and process data efficiently with LINQ. Whether you’re wiring up UI events or building dynamic business logic, understanding how to work with these features makes your code more flexible, maintainable, and expressive.

FAQs

1. Can I pass methods as parameters in C#?

Yes, using delegates like Action, Func, or custom delegate types, you can pass methods around as parameters.

2. What’s the difference between a delegate and an event?

A delegate is a function pointer. An event is a wrapper around a delegate that restricts direct invocation from outside the declaring class.

3. When should I use Func over Action?

Use Func when your delegate needs to return a value; use Action when it returns void.

4. What is the difference between lambda expressions and anonymous methods?

Both are anonymous, but lambdas use the => syntax and are more concise. They also support expression trees and LINQ better.

5. How do I unsubscribe from an event in C#?

You can unsubscribe by using the -= operator with the same method reference: eventName -= handlerMethod;

Post a Comment

Post a Comment (0)

Previous Post Next Post

ads

ads

Update cookies preferences