Week 12: Notes

events

An event is a class member that lets callers register event handlers that will receive notifications. Each event handler is a delegate. When an event is raised (i.e. fires), a notification is sent to each registered event handler. Each notification includes arguments matching the event's delegate type.

Events are useful for implementing the observer pattern, in which one or more observers may want to hear about changes to an object. A common example of this pattern is a model-view architecture, in which the view observes the model and displays the model's data. In such an architecture we want the model to be unaware of the view. Using an event, a view can register to find out when the model has changed, without giving the model specific knowledge of the view class.

Here's an array class including an event that is raised whenever any array element changes:

delegate void Notify(int index, int old, int now);

class WatchableArray {
    int[] a;
  
    public WatchableArray(int n) {
        a = new int[n];
    }
  
    public event Notify? changed;
  
    public int this[int i] {
        get => a[i];

        set {
            int prev = a[i];
            a[i] = value;
            if (changed != null)
                changed(i, prev, a[i]);  // fire the event to notify observers
        }
    }
}

Notice that the event declaration includes a delegate type, and that we can raise an event using method call syntax.

Use the += operator to register a handler with an event. For example, we can create an instance of the WatchableArray class and register an event handler:

  void onChange(int index, int old, int now) {
      WriteLine($"a[{index}] changed from {old} to {now}");
  }
  
  
WatchableArray a = new(5);
a.changed += onChange;

 

If some method later calls

  a[3] = 4;

then the above event handler will run, and will print a message such as

  a[3] changed from 0 to 4

Be warned: if you attempt to raise an event that has no registered handlers, you will get a NullPointerException. In my opinion this is a weakness in the C# event system: if would be nicer if raising such an event did nothing. However, this is how it works. So in the example above, we need to write

if (changed != null)
    changed(i, prev, a[i]);  // fire the event to notify observers

to guard against this condition.

Introduction to GTK

See the following pages, linked from our course home page: