BlackWaspTM

This web site uses cookies. By using the site you accept the cookie policy.This message is for compliance with the UK ICO law.

C# Programming
.NET 1.1+

C# Interface Events

An interface can be created to define a contract containing members that classes that implement it must provide. Interfaces can define events, sometimes leading to classes that implement several interfaces being required to declare an event name twice.

Implementing Two Interfaces

It is common for a class to implement more than one interface. This can lead to situations where a class implements two interfaces that contain members with the same name. When these members are methods or properties, at least one of the matching members must be created using explicit implementation. This is also true for event names that appear in more than one interface. As you may expect, this means that at least one event implementation must manually define the add and remove accessors.

In the final sections of this article I will describe two situations that can occur when implementing the same event name for two interfaces. To begin, we need a second interface. The INotifier type contains an event named Notify and a method that we will use to force the event to be raised. The code is as follows:

public interface INotifier
{
    event EventHandler Notify;
    void RaiseEvent();
}

Implementing Two Interfaces with Separate Events

The first way to implement two interfaces that both contain the same event name is to implement them separately. Using this method allows the events to be subscribed to individually and is ideal when the events have different meanings. In this situation, raising one of the events has no effect on the subscribers of the other.

The code below is a modified version of the Test class, which now implements both interfaces. The code starts with definitions of two private EventHandler delegates. Later in the code both events are declared explicitly and the add and remove accessors for each event refer to a single delegate.

public class Test : INotify, INotifier
{
    EventHandler _notify;
    EventHandler _notifier;
    object _lock = new object();

    event EventHandler INotify.Notify
    {
        add
        {
            lock (_lock)
            {
                _notify += value;
            }
        }
        remove
        {
            lock (_lock)
            {
                _notify -= value;
            }
        }
    }

    public void NotifyNow()
    {
        OnNotify(new EventArgs());
    }

    void OnNotify(EventArgs e)
    {
        if (_notify != null) _notify(this, e);
    }

    event EventHandler INotifier.Notify
    {
        add
        {
            lock (_lock)
            {
                _notifier += value;
            }
        }
        remove
        {
            lock (_lock)
            {
                _notifier -= value;
            }
        }
    }

    public void RaiseEvent()
    {
        OnNotifierNotify(new EventArgs());
    }

    void OnNotifierNotify(EventArgs e)
    {
        if (_notifier != null) _notifier(this, e);
    }
}

To show the operation of the above class, we need to modify the Main method and add a new event handler. The code for this is shown below. Note that both events have been subscribed to and that in each case the test object is cast to an interface type to ensure that the correct event is attached. When the code is executed, the call to the NotifyNow method raises a single event and outputs one message, as does the call to RaiseEvent.

static void Main() 
{
    Test test = new Test();
    ((INotify)test).Notify += new EventHandler(Notified);
    ((INotifier)test).Notify += new EventHandler(NotifierNotified);

    test.NotifyNow();           // Outputs "Notified"
    test.RaiseEvent();          // Outputs "Notifier Notified"
}

public static void Notified(object source, EventArgs e)
{
    Console.WriteLine("Notified");
}

public static void NotifierNotified(object source, EventArgs e)
{
    Console.WriteLine("Notifier Notified");
}
24 September 2010