DEV Community

mohamed Tayel
mohamed Tayel

Posted on

C# Advanced:Delegates

Prerequisite

Before diving into this article, please note that this is the first in the C# Advanced Series. It is recommended that you have at least 6 months of hands-on experience with C#. If you’re new or need a refresher, please explore the C# Fundamentals Series' Articles to build a solid foundation.

Introduction

Delegates in C# can be a challenging concept to grasp, but they open up a world of possibilities when it comes to writing flexible, reusable code. In this article, we'll break down what delegates are, how to use them, and why they are important in building modular and extendable applications. Additionally, you will find practical assignments at the end to solidify your understanding.

What Are Delegates?

A delegate in C# is like a pointer to a function—it defines a type-safe way to call a method without knowing its implementation. Delegates are especially useful when you need to pass methods as parameters, allowing for more dynamic and flexible code. In short, they provide a way to "delegate" work to another method.

Step-by-Step Example: Notification System

Step 1: Define the Delegate

First, define a delegate that specifies the signature of methods that will be used to notify users.

public delegate void NotifyUserDelegate(string message, string recipient);
Enter fullscreen mode Exit fullscreen mode

Step 2: Create Notification Methods

Create different methods to handle different types of notifications, such as email, SMS, and push notifications:

public void SendEmail(string message, string email)
{
    Console.WriteLine($"Email sent to {email}: {message}");
}

public void SendSMS(string message, string phoneNumber)
{
    Console.WriteLine($"SMS sent to {phoneNumber}: {message}");
}

public void SendPushNotification(string message, string deviceId)
{
    Console.WriteLine($"Push notification sent to device {deviceId}: {message}");
}
Enter fullscreen mode Exit fullscreen mode

Step 3: Create a Method to Use the Delegate

Create a method that takes a delegate as a parameter to notify users using different methods.

public void NotifyUser(NotifyUserDelegate notifyMethod, string message, string recipient)
{
    notifyMethod(message, recipient); // Invoke the method passed as a delegate
}
Enter fullscreen mode Exit fullscreen mode

Step 4: Assign Methods to the Delegate and Call NotifyUser

Finally, assign different notification methods to the delegate and use it to notify users.

NotifyUserDelegate emailNotifier = SendEmail;
NotifyUserDelegate smsNotifier = SendSMS;
NotifyUserDelegate pushNotifier = SendPushNotification;

NotifyUser(emailNotifier, "Your order has been shipped!", "user@example.com");
NotifyUser(smsNotifier, "Your package is out for delivery.", "+123456789");
NotifyUser(pushNotifier, "Your order has been delivered!", "device12345");
Enter fullscreen mode Exit fullscreen mode

Full Code for Notification System Example

using System;

public class NotificationExample
{
    // Step 1: Define the delegate
    public delegate void NotifyUserDelegate(string message, string recipient);
    // Step 2: Create notification methods
    public void SendEmail(string message, string email)
    {
        Console.WriteLine($"Email sent to {email}: {message}");
    }
    public void SendSMS(string message, string phoneNumber)
    {
        Console.WriteLine($"SMS sent to {phoneNumber}: {message}");
    }
    public void SendPushNotification(string message, string deviceId)
    {
        Console.WriteLine($"Push notification sent to device {deviceId}: {message}");
    }
    // Step 3: Create a method to use the delegate
    public void NotifyUser(NotifyUserDelegate notifyMethod, string message, string recipient)
    {
        notifyMethod(message, recipient); // Invoke the method that was passed as a delegate
    }
    // Step 4: Run the example
    public void RunExample()
    {
        NotifyUserDelegate emailNotifier = SendEmail; 
        NotifyUserDelegate smsNotifier = SendSMS; 
        NotifyUserDelegate pushNotifier = SendPushNotification; 
        // Notify via email
        NotifyUser(emailNotifier, "Your order has been shipped!", "user@example.com");
        // Notify via SMS
        NotifyUser(smsNotifier, "Your package is out for delivery.", "+123456789");
        // Notify via push notification
        NotifyUser(pushNotifier, "Your order has been delivered!", "device12345");
    }
    // Entry point
    public static void Main()
    {
        NotificationExample example = new NotificationExample();
        example.RunExample();
    }
}

Enter fullscreen mode Exit fullscreen mode

Benefits of Using Delegates

  • Flexibility: You can decide at runtime how to perform certain actions.
  • Extensibility: Easily add new functionalities without changing the existing code.
  • Modularity: Delegates help you decouple your code, making it more reusable and maintainable.

Assignments

Easy Level

  1. Objective: Implement a Calculator using delegates.
  2. Instructions:
    • Define a delegate named MathOperation that takes two integers and returns an integer.
    • Create methods for addition, subtraction, multiplication, and division.
    • Write a method named PerformOperation that takes a MathOperation delegate and two integers and uses it to perform the operation.

Example Usage:

PerformOperation(addition, 5, 3); // Output: 8
Enter fullscreen mode Exit fullscreen mode

Medium Level

  1. Objective: Build a simple Event Logger using delegates.
  2. Instructions:
    • Define a delegate named LogHandler that takes a string message.
    • Create different logging methods, such as ConsoleLogger to log to the console and FileLogger to log to a text file.
    • Use a method named LogEvent that takes a LogHandler and logs various events, such as "User logged in", "File uploaded", etc.

Example Usage:

LogEvent(ConsoleLogger, "User logged in"); // Logs to console
LogEvent(FileLogger, "File uploaded"); // Logs to file
Enter fullscreen mode Exit fullscreen mode

Difficult Level

  1. Objective: Create a Workflow Engine using delegates.
  2. Instructions:
    • Define a delegate named WorkflowStep that takes no parameters and returns nothing.
    • Create methods that represent different steps of a workflow, such as StartProcess, ProcessData, and EndProcess.
    • Write a method named RunWorkflow that takes an array of WorkflowStep delegates and runs each step sequentially.

Example Usage:

WorkflowStep[] workflowSteps = { StartProcess, ProcessData, EndProcess };
RunWorkflow(workflowSteps); // Runs each step in sequence
Enter fullscreen mode Exit fullscreen mode

Conclusion

Delegates can add a lot of power to your applications, making them more flexible and easier to extend. By working through the example and completing the assignments, you'll gain a solid understanding of how delegates work and how you can use them to write more modular code.

Call to Action

Did you enjoy this step-by-step guide? Try out the assignments and see how far you can push the flexibility of your code with delegates. Feel free to share your solutions and challenges in the comments below!

Top comments (0)