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.

Declaring Events in Interfaces

In a previous article that formed part of the C# Object-Oriented Programming tutorial, I described the use of interfaces, which can be used to create contracts for classes. In that article were examples of interfaces that enforced the inclusion of methods and properties in the classes that implemented them. Interfaces are not limited to defining methods and properties. They can include other member types, such as events.

In this article we will look at how events can be included in interfaces and how they are added to classes using implicit or explicit implementation. We will also examine the rare but important situation where a class implements two interfaces that each contain an event with the same name.

Defining an Interface Event

To demonstrate the use of events within interfaces we need an interface to work with. To follow the examples, create a new console application and add the following interface to the project. This interface includes an event named, "Notify". The NotifyNow method is an artificial item that we will use to force the event to be raised.

public interface INotify
{
    event EventHandler Notify;
    void NotifyNow();
}

Implementing an Interface Event

We can now create a class that implements the INotify interface. The Test class defined below achieves this by declaring the event as a public member. The public NotifyNow method simply calls the private OnNotify method, which in turn raises the event if there are any subscribers. The syntax of the event and the OnNotify method that raises it are no different to that of an event that is not defined in an interface.

public class Test : INotify
{
    public event EventHandler Notify;

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

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

To test that the event is functioning correctly, add the following code, replacing the Main method of the console application, and run the program. The updated Main method creates a new Test object as a variable of the INotify type. It subscribes to the event and then calls the Notify method to force the event to be raised. When the event is raised, the subscribed Notified method is executed and a message is outputted to the console.

static void Main() 
{
    INotify test = new Test();
    test.Notify += new EventHandler(Notified);
    test.NotifyNow();           // Outputs "Notified"
}

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

Explicitly Implementing an Interface with an Event

As described in the earlier article, sometimes you will want, or need, to implement an interface explicitly. When implementing an interface event explicitly you must also define the add and remove accessors for the event manually. We can see this in the example code below where the INotify.Notify event has been modified and is now declared in full. Try making the changes and running the program again. You should see no difference in the output as the event still works correctly and the test variable is declared using the interface type.

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

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

    void INotify.NotifyNow()
    {
        OnNotify(new EventArgs());
    }

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