Events in C#: When and How to Implement Them
ByteHide
Posted on December 20, 2023
Welcome! You’ve probably been hearing a lot about C# events, but you’re wondering, How does it all tie together? Just sit back, because in this article, you are going to catch up on all the details about C# events and their application.
It’s like learning to play an instrument; before you start composing, you need to understand how to read the musical notes. Before diving into the advanced stuff, let’s understand the basics. Stick with me, and I promise, you’ll be writing captivating symphonies – I mean, coding in C# in no time!
Introduction to C# Events
Hang on, what really is a C# event? Covert operations? Nope! In the world of C#, an event is simply a way that a class can notify other classes or objects when something of interest happens.
Overview of Events in C#
Events in the context of C#. Imagine you’re at a concert. The band playing is the publisher of events (C# class), and the audience (other classes or objects) is waiting for something noteworthy (an event) to happen. When the band starts playing (an event occurs), the audience reacts (responds to the event). In programming terms, events in C# provide notification when a specific action has occurred in an object.
public class AlarmClock
{
public event Action AlarmSounded;
public void Start()
{
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(5));
AlarmSounded?.Invoke();
}
}
public class Person
{
public void WakeUp() => Console.WriteLine("Waking Up!");
}
public class MainProgram
{
public static void Main()
{
AlarmClock alarmClock = new AlarmClock();
Person person = new Person();
alarmClock.AlarmSounded += person.WakeUp;
alarmClock.Start();
}
}
In this code snippet, the AlarmClock
class publishes the AlarmSounded
event, which the Person
class listens to. When the AlarmSounded
event is fired after 5 seconds, the person’s wake-up method responds.
Role of Event Handlers in C#
In a festival, event organizers handle everything, right? Similarly, in C#, event handlers handle the response to an event.
What is an Event Handler in C#
In C# event handling, an “event handler” is a delegate that gets called when a given event is fired. Like a listener who is waiting for their favorite song to play, the event handler is waiting for the right event to take action.
public class Button
{
public event EventHandler Clicked;
public void PressButton()
{
Clicked?.Invoke(this, EventArgs.Empty);
}
}
public class User
{
public void PerformAction()
{
Console.WriteLine("Action Performed!");
}
}
public class MainProgram
{
public static void Main()
{
Button button = new Button();
User user = new User();
button.Clicked += user.PerformAction;
button.PressButton();
}
}
In the example above, the User
class has a method PerformAction
that serves as an event handler. Whenever the Button
is pressed (event happens), the user performs a particular action.
Implementing Events in C#
Ah! The practical aspect of any programming language, that’s where the real fun begins, isn’t it? It’s time to swing into action and see how we can implement events in C#. Let’s roll up our sleeves and dive into the coding part!
Step-by-Step Guide to Implementing Events in C#
Implementing events in C# is like taking a step-by-step journey of orchestrating when and how certain actions are responded to in your program. Remember, it’s a journey best taken one step at a time. Let’s break down the process:
- Define a delegate that matches the signature of the event handler method you want to use.
- Declare an event using the delegate you defined.
- Implement a method, within the provider class, that raises the event.
- Create a method in the subscriber class that will handle the event (conforms to the delegate).
- Subscribe the event handling method to the event.
Sounds like a lot? Let’s simplify this with a real-world example.
Real-World C# Event Example
How about we consider a traffic light system? The lights changing (events) cause cars to react (event handling) accordingly. Here is a simplified version of how this could be coded:
// step 1: define a delegate
public delegate void TrafficLightChangedHandler(string color);
public class TrafficLight
{
// step 2: declare an event
public event TrafficLightChangedHandler TrafficLightChanged;
public void ChangeLight(string color)
{
// step 3: method that raises the event
Console.WriteLine($"The traffic light is {color}.");
TrafficLightChanged?.Invoke(color);
}
}
public class Car
{
public void ReactToLight(string lightColor)
{
// step 4: event handling method
if (lightColor == "Red")
{
Console.WriteLine("Car stops.");
}
else if (lightColor == "Green")
{
Console.WriteLine("Car starts moving.");
}
}
}
public class MainProgram
{
public static void Main(string[] args)
{
TrafficLight light = new TrafficLight();
Car car = new Car();
// step 5: subscribe to the event
light.TrafficLightChanged += car.ReactToLight;
light.ChangeLight("Green");
light.ChangeLight("Red");
}
}
In the code above, when the traffic light color changes, the event TrafficLightChanged
is fired and causes the car to react. If the light is green, the car moves; if it’s red, the car stops.
Let’s return to the email sending example. In addition to sending the email, we may also need to acknowledge the recipient that the email is being sent.
public class Recipient
{
public void OnAcknowledge(string recipient)
{
Console.WriteLine($"Email is being sent to {recipient}");
}
}
public class MainProgram
{
public static void Main(string[] args)
{
EmailAcknowledge emailAck = new EmailAcknowledge();
Recipient recipient = new Recipient();
emailAck.AcknowledgeSending += recipient.OnAcknowledge;
emailAck.Acknowledge("Bob");
emailAck.Acknowledge("Alice");
}
}
In the newly introduced code snippet, when the Acknowledge
method in the EmailAcknowledge
class is called, it raises the event AcknowledgeSending
, which the Recipient
class is listening to. As soon as this event is raised, the OnAcknowledge
method in Recipient
class gets called and the name of the recipient is printed.
Working with EventArgs in C#
Whew! You’ve made it far. Next stop is EventArgs
town. Ready?
Understanding C# Event Args
In C#, ‘EventArgs’ is a class that provides data related to an event. Think of EventArgs as the courier carrying the message that an event has occurred.
public class SongPlayedEventArgs : EventArgs
{
public string PlayedSong { get; set; }
}
public class MusicPlayer
{
public event EventHandler<SongPlayedEventArgs> SongPlayed;
public void PlaySong(string song)
{
SongPlayed?.Invoke(this, new SongPlayedEventArgs() { PlayedSong = song });
}
}
public class Listener
{
public void OnSongPlayed(object sender, SongPlayedEventArgs e)
{
Console.WriteLine($"'{e.PlayedSong}' has been played.");
}
}
In this example, SongPlayedEventArgs
carries the name of the song that’s been played. Listener
uses this custom data (PlayedSong
) to respond to the SongPlayed
event.
Advanced Concepts in C# Event-Handling
Take a deep breath, grab a coffee if needed, because we’re about to delve deeper into the abyss of C# events. Just like building a towering Lego skyscraper, it’s all about understanding the intricacies and techniques to assemble the blocks effectively.
Safe Event Invocation
One of the essential aspects of event handling in C# is to always ensure safe event invocation. Listener classes might unsubscribe to an event at any given point in time. Invoking an event without any subscribed listeners could lead to a null reference exception – and trust me, we don’t like those, do we?
Here’s how to safely invoke events:
public class Publisher
{
public event EventHandler<EventArgs> OnPublish;
public void Publish()
{
OnPublish?.Invoke(this, EventArgs.Empty);
}
}
The ?.
syntax is C#’s shortcut for null checking before invoking the event handlers, saving us from possible null reference exceptions. It’s as though you’re checking if the coffee machine is indeed present before pressing the brew button.
Passing Data Using Custom EventArgs
In many scenarios, we need to pass some data along with our events. That’s where custom EventArgs come into the picture.
Let’s suppose you’re building an app for a library which fires an event whenever a new book arrives.
public class NewBookEventArgs : EventArgs
{
public string Title { get; set; }
public string Author { get; set; }
}
public class Library
{
public event EventHandler<NewBookEventArgs> OnNewBookArrived;
public void AddBook(string title, string author)
{
OnNewBookArrived?.Invoke(this, new NewBookEventArgs { Title = title, Author = author });
}
}
public class Member
{
public void OnNewBookArrived(object sender, NewBookEventArgs e)
{
Console.WriteLine($"New book arrived! Title: {e.Title}, Author: {e.Author}");
}
}
Here, we created a NewBookEventArgs
class that inherits from EventArgs
and added two properties: Title
and Author
. We fire the event by creating a new instance of NewBookEventArgs
and passing it along with the event invocation.
This way, event handlers (like OnNewBookArrived
from the Member
class) can access this data and act accordingly.
Unsubscribing from Events
Here’s the thing: every time a class subscribes to an event, it forms a strong reference with the event source. This reference can stop the garbage collector from reclaiming the memory, leading to potential memory leaks (aka, the silent resource murderers!).
Just as you would turn off the lights before exiting a room or unsubscribe from an annoying newsletter in your inbox, remember to unsubscribe from events when they are no longer necessary.
public class Publisher
{
public event Action OnPublish;
}
public class Subscriber
{
public void OnPublishing()
{
Console.WriteLine("Something has been published!");
}
public void Register(Publisher publisher)
{
publisher.OnPublish += OnPublishing;
}
public void Unregister(Publisher publisher)
{
publisher.OnPublish -= OnPublishing;
}
}
public static class Program
{
public static void Main()
{
Publisher publisher = new Publisher();
Subscriber subscriber = new Subscriber();
subscriber.Register(publisher); // Subscribing to the event
publisher.OnPublish?.Invoke();
subscriber.Unregister(publisher); // Unsubscribing from the event
publisher.OnPublish?.Invoke();
}
}
The Register
and Unregister
methods handle the subscription and unsubscription from the publisher.OnPublish
event. Simple enough, right? Yes, it’s like you’re giving your consent to receive those marketing emails. And when you decide you’ve had enough? Simply unsubscribe!
Conclusion
Events and the Future of C# Programming
Wow, quite a journey, right? Have events become your new best friends? They should, as encapsulation of behaviours into events streamlines your code, makes it cleaner, and more efficient. It might seem like a challenge now, but the more you meditate on this knowledge, the easier it will be to grasp its essence.
So, go ahead, experiment with some code. Remember, in programming, just as in life, practice makes perfect! Happy coding, folks!
Posted on December 20, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.