Yearly Archives

16 Articles

Programming/C#

Learning C# Events

Posted by matteskolin on

In everyday usage, an event is something noteworthy that happens, a special occasion, or a change of the state of something.

Examples of events might include a birthday party, waking up in the morning, arriving at work, water starting to boil, or a plane landing.

In these examples, each of these events happen within a context to a subject. Depending on what we are interested in we can define the subject in different ways. For a birthday party, the subject might be the person celebrating, or it might be the venue where the party is held. Likewise, A specific plane lands, I arrive at my office, or flight #234234 arrives in Minneapolis.

In C# terms this subject is the publisher of the event. Events happen in a specific context. For a long time, I was confused about this in c# and assumed that events could just pop up anywhere. However, events can only be raised from within a class that declares the event.

    public class Airplane {

        //define events that occur in the context of an Airplane Object
        public event EventHandler OnLanding;
        public event EventHandler OnTakeOff;
        public event EventHandler OnFlightComplete;     
        
    }

The above class declares an Airplane type with three events. These events are things that are noteworthy occurrences to that airplane such as Landing, Taking off, and Completing the Flight.

These field-like declarations are made with the EventHandler delegate type which is part of the System.Runtime assembly.

For events to be useful, we need a subscriber who is interested in events that occur. Let’s consider a traffic controller who is monitoring a list of planes.

   public class AirTrafficController{

        public List<Airplane> Planes {get; set;}


        public AirTrafficController(List<Airplane> planes)
        {
            Planes = planes;
            Planes.ForEach(x => x.OnLanding += OnPlaneLanding);
        }

        public void OnPlaneLanding(object sender, EventArgs eventArgs){

            var airplane = sender as Airplane;
            Console.WriteLine($"Plane {airplane.Name} has landed");
        }
    } 

In the above class, the AirTrafficController has a reference to a list of planes. The class subscribes to the OnPlaneLanding event in the second line of the constructor.

Now, whenever a plane lands the air traffic controller will be notified. Below is the updated Airplane class, I have added a main method which will show the publishing (Airplane), Subscribing(AirTrafficController), and consuming (OnPlaneLanding method) of the event.

Notice the use of the += operator when subscribing to the event. When the event occurs in the Airplane class, all subscribers will be notified. When the event is triggered all delegates that have been added are called. by calling the methods on the right side of this operator from all subscribing classes.

We can think of the AirTrafficController OnPlaneLanding as ‘handling’ the event.

    public class Airplane {

        //define events that occur in the context of an Airplane Object
        public event EventHandler OnLanding;
        public event EventHandler OnTakeOff;
        public event EventHandler OnFlightComplete;
      
       public string Name {get; set;}

        public Airplane(string name)
        {
            Name = name;           
        }

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

    }

    class Program
    {
        static void Main(string[] args)
        {
            var planes = new List<Airplane>(){
                new Airplane("Plane 1"),                
                new Airplane("Plane 2"),
                new Airplane("Plane 3"),          
                new Airplane("Plane 4")
            };

            var airTrafficcontroller = new AirTrafficController(planes);

            planes.ForEach(x => x.LandPlane());
        }
    }

Our main method creates four planes and assigns them to an AirTrafficController. When the main method calls the LandPlane() method, the air traffic controller is notified, and the following is output to the screen.

Plane Plane 1 has landed
Plane Plane 2 has landed
Plane Plane 3 has landed
Plane Plane 4 has landed