Author avatar

Dániel Szabó

Writing Custom Event Accessors in C#

Dániel Szabó

  • Jan 21, 2020
  • 5 Min read
  • 315 Views
  • Jan 21, 2020
  • 5 Min read
  • 315 Views
Languages Frameworks and Tools
C#

Introduction

In order to understand custom event accessors, we need to clarify why they are needed and how they are used. In this guide, we will introduce the concept of events, then take a look at how events and their accessors can be used to interact between classes. In C#, a typical example of this would be a Windows Forms or Web Application.

Events

Let's take a live example. We have a GUI (Graphical User Interface) application, which consists of buttons, text boxes etc. Each component is made up of its own class, and each class provides a functionality—for example, a button push sends a notification to a web application or invokes a local application on the machine. At the very heart of this are events. We categorize classes either by publisher or subscriber. The publisher is the class that sends or raises the event, and the subscriber receives the event and takes specific action based on it.

Rules for Events

A few rules to keep in mind when it comes to events:

  1. The publisher determines when an event is raised.
  2. The subscriber determines what action is taken when a specific event is fired.
  3. Events without subscribers are never raised.
  4. Events mostly get fired due to user interactions, either on a web app or GUI app.
  5. By default, an event that has multiple subscribers gets its handler invoked synchronously, unless defined in asynchronous fashion.
  6. The events are based on EventHandler delegates and EventArgs base class.

Steps of Event Creation

  1. Create a delegate, which holds the details of the subscribers to an event.
  2. Create a public event that is externally visible to the class and used for creating subscriptions.
  3. Create the method in the class, which will fire the event itself.

Custom Event Handlers

I believe it's best to demonstrate this with a mechabot example, for which the code looks like this.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
using System;
namespace Pluralsight
{
    public class Machine
    {
        private int _utilization = 0;
        private int _safeutil = 70;        
        public delegate void StressLimitExceededEventHandler(object source, EventArgs e);
        public event StressLimitExceededEventHandler StressLimitExceeded;
        public virtual void OnStressLevelExceeded(EventArgs e)
        {
            StressLimitExceeded?.Invoke(this, e);            
        }
        public int Performance
        {
            get
            {
                return _utilization;
            }
        }
        static void MachineStressLimitExceeded(object source, EventArgs e)
        {
            Machine mechabot = (Machine)source;
            Console.WriteLine("Stress level warning ({0} %)", mechabot.Performance); 

            
        }
        public void StressTest(int utilization)
        {
            int oldUtilization = _utilization;
            _utilization += utilization;

            if (oldUtilization <= _safeutil && _utilization > _safeutil)
                OnStressLevelExceeded(new EventArgs());
        }
        public static void Main()
        {
            Machine mechabot = new Machine();
            mechabot.StressLimitExceeded += new StressLimitExceededEventHandler(MachineStressLimitExceeded);
            Console.WriteLine($"The utilization is {mechabot.Performance} %");
            mechabot.StressTest(60);
            Console.WriteLine($"The utilization is {mechabot.Performance} %");
            mechabot.StressTest(15);
            Console.WriteLine($"The utilization is {mechabot.Performance} %");
            Console.ReadKey();
        }
    }
}
csharp

Executing the code produced the following output.

1
2
3
4
The utilization is 0 %
The utilization is 60 %
Stress level warning (75 %)
The utilization is 75 %
bash

Let's dissect the example. The Main() function is what drives the whole demonstration. We have a StressTest function, which takes a utilization argument, which will increase the mechabot's utilization. In here we check whether the old utilization and the one after the increase surpass _safeutil, which is set to 70. One of the most important concepts of event handling is demonstrated here in which the OnStressLevelExceeded is fired when the conditions are met. The delegate we have is called StressLimitExceededEventHandler, and it is responsible to hold the details of the subscriber to the event. The event StressLimitExceededEventHandler is also created, which will be able to provide us with the subscription. The associated event method is called OnStressLevelExceeded and will be invoked when the subscribed event is fired and the conditions are met. This class is glued together by this concept and provides a sufficient demonstration as to how you can create your own event handlers.

Conclusion

In this guide you received a short introduction to events and some general rules and steps for creating them. Then the Machine class demonstrated how to glue the concepts together and how event handlers can be incorporated into your application. I hope this has been informative to you and I would like to thank you for reading it.

3