Skip to main content

Command Palette

Search for a command to run...

C# Event

Updated
8 min read
C# Event

Introduction

Hello all, today I back with another C# topic, and today I will share what i learned about C# Event. I hope with this article you will know more about C# Event and use it on your project.

Before diving deeper into C# Event, it’s recommended to first read my C# Delegate post at C# Delegate - Last Night Codes.

What It Is?

In C#, an event is a specialized form of delegate. Unlike delegates, which allow methods from outside the class to be assigned using both = and += operators, an event restricts assignments to only using the += operator. Additionally, events can only be raised within the class where they are declared, ensuring that they are raised only in controlled circumstances.

Why Implement It?

There are several pros and cons to consider before implement an event in our project. Here are some of them:

Pros

  • Enhance the clarity of the code flow.

  • Minimize dependencies on other classes.

  • Preventing direct invocation of a delegate from outside its declaring class reduces the risk of unintended side effects.

Cons

  • It may be challenging for new programmers to understand.

  • Could potentially cause performance overhead if there's too many method assign to it.

  • Could potentially cause memory leaks If the event are not properly unsubscribed.

How It Works?

To understand how event work in the system, let's implement it first. To implement an event, all you need to do is add an event keyword in front of the delegate, there are two different types of delegate that can be used for an event:

  1. Regular Delegates e.g. public event [delegate/Action/Func/Predicate] OnOpenButtonPressed;

  2. Event Handler Delegates e.g. public event EventHandler CloseButtonPressEventHandler;

To learn more about the differences between regular delegates and event handler delegates, see the section on Regular Delegates vs. Event Handler Delegates below.

The implementation of these events is as shown in the code below:

using System;

namespace Lncodes.Example.Event;

public abstract class UIController
{
    public event Action OnOpenButtonPressed;
    public event EventHandler CloseButtonPressEventHandler;
}

In the code above, I have created events using the Action delegate and the EventHandler delegate. These events are designed to be triggered whenever the open or close button is pressed. After implementing these events in the code, here's what will happen in the system:

  1. When a delegate is declared as an event, the system ensures that the event can only be raised within the class that declares it. Additionally, methods can only be assigned to the event using the += operator.

  2. Assigning and raising an event is similar to working with a delegate. When you assign a method to an event, it references that method. Raising the event will then also invoke all methods that have been added to it.

Console Application

In my console application, an event is used to display a message when a button is pressed. This console application uses three different types of delegates: Action (a general delegate without arguments), EventHandler (a specialized delegate without specific arguments), and EventHandler<T> (a specialized delegate with specific arguments).

Below is a list of the classes I used to create this console application, along with a brief explanation of each class:

ClassDescription
UIControllerThis class is used as a parent class that manages general UI-related operations for all menu classes.
MainMenuUIControllerThis class is used to manage UI-related operations for the main menu.
ResultMenuUIControllerThis class is used to manage UI-related operations for the results menu.
CloseButtonEventArgsThis class is used to store event data that is passed through an EventHandler.
ProgramThis class is used to display button pressed events messages on the console.

In the video above, the console application displays a message when the button is pressed. There are three different buttons, each representing a different type of delegate used to handle events. Below is a list of all the delegate types used in this console application, along with a brief explanation of each delegate:

Delegate TypesDescription
event ActionThis delegate is used to handle the event that is raised when the open button is pressed. The output can be seen in the console message no 1.
event EventHandlerThis delegate is used to handle the event that is raised when the animate button is pressed. The output can be seen in the console message no 2.
event EventHandler<String>This delegate is used to handle the event that is raised when the close button is pressed. The output can be seen in the console message no 3.

By implementing events, managing and handling button actions becomes significantly more efficient. Additionally, using different delegate types for various events can further enhance action management. Each delegate type is designed to ensure that events are handled appropriately, leading to a more organized and effective event-handling process.

The source code for this console application can be viewed and downloaded at Project Repository – Github.

Additional Information

I have discovered some additional information about C# Event. If you have any additional information about C# Event that you'd like to share, please feel free to leave a comment.

Naming Guidelines

When implementing events, following specific naming guidelines can help ensure code readability and consistency. Here are some naming conventions recommended by Microsoft:

  • Do use a verb or verb phrase when naming an event e.g., opening, closed, etc.

  • Do use verb-ing for event names that are raised before an operation is performed e.g., opening, closing, etc.

  • Do use verb-ed for event names that are raised after an operation is performed e.g., opened, closed, etc.

  • Do use 'On' prefix for the regular delegate event names, e.g. public event Action OnOpenButtonPressed;.

  • Do use 'EventHandler' suffix for event handler delegate event names e.g. public event EventHandler CloseButtonPressEventHandler;.

  • Do use the 'EventArgs' suffix for class or struct names that are intended to be used as arguments for EventHandler e.g. public class CloseButtonEventArgs { }.

  • Do use the 'On' prefix for method names that raise an EventHandler e.g. protected void OnOpenButtonPressed().

Regular Delegate VS Event Handler Delegate

Both regular delegates and event handler delegates have similar functionality to managing method references within an event-driven architecture. Due to these similarities, choosing between them can be challenging. Here are some key factors to consider before making a decision:

  • When using EventHandler, there are two default parameters: sender and eventArgs. In contrast, regular delegates do not include these default parameters.

  • Use EventHandler when it’s important to know which object raised the event. For instance, in an inheritance architecture, EventHandler helps determine which child class is raising the event, thanks to its default sender parameter which provides the instance of the object that raised the event.

In my opinion, any delegate with two arguments (the sender and the event data) can be considered as an event handler delegate type, even if it's declared using a regular delegate e.g. public event Func<int, object, EventArgs> OpenButtonEventHandler.

Event VS Delegate

Both events and delegates have similar functionality to manage method references and provide a way to register methods. Due to these similarities, choosing between them can be challenging. Here are some key factors to consider before making a decision:

  • An event is typically used to notify the subscribing classes when something occurs in the publisher class, while a delegate is typically used for callbacks or to pass methods as parameters.

  • An event can only be raised within the class where it’s declared, while a delegate can be invoked from outside its declaring class. This restriction helps ensure that the event’s handling remains encapsulated within the class that declares it.

  • Outside its class declaration, an event can only be modified by adding or removing event handlers using the += and -= operators. In comparison, a delegate can be can be assigned or modified using =, +, -, +=, and -= operators.

💡
To learn more about C# Delegate, check out my post at C# Delegate - Last Night Codes.

Further Discoveries

Here are some further discoveries I have gathered from various sources that may provide a deeper understanding of C# Event:

  • When using EventHandler and no additional arguments are needed, it's recommended to use EventArgs.Empty instead of null. This maintains consistency and prevents null reference errors at runtime.

  • When using a static EventHandler, it's acceptable to pass null for the sender argument. However, for non-static EventHandler instances, avoid passing null as the sender argument.

  • When using the EventHandler delegate for an event, it’s essential to define a method to raise the event, and this method should be marked as protected virtual. This allows subclasses to override the method and raise the event, which is essential for properly implementing event handling in an inheritance-based architecture.

  • When an EventHandler that returns values is required, a custom EventHandler can be defined using a regular delegate, like public event Func<int, object, EventArgs> CloseButtonPressEventHandler.

  • Since C# 2.0, the generic EventHandler<T> can be used to define the type of argument for an EventHandler. This approach is recommended when the EventHandler needs to pass an argument, as it eliminates the need to cast the EventArgs parameter to access the argument value.

Reference

  1. C# Event – Microsoft

  2. C# Event Handler – Microsoft

  3. C# Event Design Guidelines – Microsoft

  4. C# Event Naming Guidelines – Microsoft

C#

Part 6 of 7

In this series, I’ll share the most important lessons and discoveries I’ve acquired about C#. From fundamental concepts to advanced features, discover how these lessons have sharpened my coding skills and how they can benefit to my projects.

Up next

C# Abstract

Introduction Hello all, today I back with another C# topic, and today I will share what i learned about C# Abstract. I hope with this article you will know more about C# Abstract and use it on your project. What It Is? An abstract class acts as a blu...

More from this blog

L

Last Night Codes

11 posts

Last Night Codes shares my journey through learning different programming languages and documenting my projects. Explore practical tips, insights, and personal coding experiences.