C# .NET

Simplifying C# Event Handling with Delegates

Bhushan Kadam
Cover Image for Simplifying C# Event Handling with Delegates

Introduction

In C#.NET, Events and delegates are key programming concepts. Being a C#.NET Developer you will definitely get a requirement where you will need to use Events and Delegates. In this blog post, we will understand the basics of Events and Delegates. We will also look at their types. We will also see some practical examples of using Events and Delegates in C#.NET. So stay tuned.

The primary use of Events and Delegates in C#.NET is to facilitate communication between classes in an application. Let's understand this in detail by first exploring what are Delegates and events individually. Then we will look at how they work with each other hand in hand.

Delegates

In C#.NET, a delegate is a type. Using delegates, we can define a method signature. This method signature can act as a pointer to a method. Using this mechanism we can pass a method as an argument to another method. This provides us flexibility in how the method is executed, as any method with the correct signature can be used as a delegate.

C#.NET provides a keyword delegate that we can use to define a new delegate. It needs to be followed by the method signature.

For example, let's look at the below code snippet. Here we have defined a new delegate for a method named TestDelegate. It defines a method signature that takes two integers number1 and number2 as input and returns a bool value.

public delegate bool TestDelegate(int number1, int number2);

Once this delegate is defined, we can use it and assign it to a method having the same signature. Let's take a look at the below example to understand this better.

private bool TestMethod(int number1, int number2) 
{
     return true;
}

TestDelegate td = new TestDelegate(TestMethod);

In this example, we have created a new instance of delegate TestDelegate and assigned the method TestMethod to it. The important point here is that the TestMethod has the same method signature defined by TestDelegate.

C#.NET also provides a shorthand operator += to assign a method to a delegate.

private bool TestMethod(int number1, int number2) 
{
     return true;
}

TestDelegate td += TestMethod;

Once the method is assigned, we can invoke this delegate using the delegate variable define. Let's take a look at the below example.

bool result = td(5, 10);

The most ideal use of Delegates is in event-driven programming. In event-driven programs, a class can raise an event and other classes can respond to the event by handling it with a method having the same signature as the delegate.

C#.NET also provides some predefined delegates such as EventHandler and EventHandler<TEventArgs>. The EventHandler<TEventArgs> is a generic delegate type. We can use these delegates instead of defining our own delegate types to make the code simple if it serves the purpose.

Events

C#.NET provides a mechanism called Event that allows a class to notify other classes about some action that has occurred. Using events, the classes can communicate with each other. A class creates an event and other classes in the application can respond to that event and change their own state accordingly.

C#.NET provides a keyword event that can be used to declare an event in the class. The class that wants to raise an Event is known as a Publisher class. The publisher class defines the event by creating a delegate field and an event field. Let's take a look at the below example to understand this.

public class CustomButton
{
    public delegate void ClickEventHandler(object sender, EventArgs e);
    public event ClickEventHandler Click;

    //Rest of the code here
}

In this example, we created a class CustomButton. We have declared a delegate ClickEventHandler and also an event Click. Here CustomButton will act as a publisher class and all the other class in the application which uses this class can be called Subscriber classes. They can handle this click event by attaching a method to it.

To raise an event, the Subscriber class will give a call to the event field as shown below.

private void OnClick(object sender, EventArgs e)
{
    if (Click != null)
    {
        Click(sender, e);
    }
}

The subscriber class can handle this event by adding the method to it using += operator. Again as we learned earlier, the method in subscriber must have the same signature as the delegate defined by the publisher.

CustomButton button = new CustomButton();
button.Click += HandleClick;

private void HandleClick(object sender, EventArgs e)
{
    Console.WriteLine("CustomButton clicked event occurred!");
}

With this example, we understood how we can use events to communicate between the classes and respond to the changes in the application. They are an essential part of programming in C#.NET and are used in a wide variety of applications, from UI to data processing.

Practical Examples of Events and Delegates

Now that we have understood what events and delegates are, let's take a look at some practical examples of their usage.

Button Click Event Handlers

This is a common use case for events in UI applications. In UI applications, the button class raises a Click event when the button is clicked. The subscriber class can handle the event by adding a method to the event with the same signature as the delegate.

public class TestButton
{
    public delegate void ClickEventHandler(object sender, EventArgs e);
    public event ClickEventHandler Click;

    public void OnClick()
    {
        if (Click != null)
        {
            Click(this, EventArgs.Empty);
        }
    }
}

TestButton button = new TestButton();
button.Click += HandleClick;

private void HandleClick(object sender, EventArgs e)
{
    Console.WriteLine("Test Button was clicked!");
}

File System Watcher

Another example of events is in a file system watcher class that raises events when a file or directory is created, deleted, or modified. The subscriber class can handle the event by adding a method to the event with the same signature as the delegate.

public class FileWatcher
{
    public delegate void FileChangedEventHandler(object sender, FileSystemEventArgs e);
    public event FileChangedEventHandler FileChanged;

    public void StartWatching()
    {
        // Code to watch for file system changes
        if (FileChanged != null)
        {
            FileChanged(this, e);
        }
    }
}

FileWatcher watcher = new FileWatcher();
watcher.FileChanged += HandleFileChanged;

private void HandleFileChanged(object sender, FileSystemEventArgs e)
{
    Console.WriteLine($"File {e.FullPath} was {e.ChangeType}");
}

Asynchronous Programming

Events and delegates are often used in asynchronous programming, where a class raises an event when a long-running task is complete. The subscriber class can handle the event by adding a method to the event with the same signature as the delegate.

Please read this blog post to read more about asynchronous programming in C#.NET.

public class AsyncTask
{
    public delegate void TaskCompletedEventHandler(object sender, EventArgs e);
    public event TaskCompletedEventHandler TaskCompleted;

    public async Task StartAsync()
    {
        // Code to perform async task
        if (TaskCompleted != null)
        {
            TaskCompleted(this, EventArgs.Empty);
        }
    }
}

AsyncTask task = new AsyncTask();
task.TaskCompleted += HandleTaskCompleted;

private void HandleTaskCompleted(object sender, EventArgs e)
{
    Console.WriteLine("Async task completed");
}

Conclusion

Events and Delegates are powerful tools in C#.NET. We understood how they can be efficiently used for communication between classes in an application. We also saw practical examples of where they can be applied easily.

Thank you for taking the time to read this blog post. We hope that you found the information provided in the blog to be helpful and informative. For similar content, please check out our other blogs.

We appreciate your support and feedback, and we would love to hear from you if you have any questions or comments about the blog. If you have any specific topic you want us to cover in the future, please feel free to let us know.

Once again, thank you for reading our blog, and we look forward to your continued support.