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.

.NET Framework
.NET 1.1+

Using the EventHandler Delegate

When creating custom events, a delegate is declared to control the parameters that the event passes to the subscriber when the event is raised. For simplistic events with no requirement to pass information, the built-in EventHandler delegate can be used.

Events and Event Arguments

Usually when an event is raised, it passes related status information to its subscribers. For example, a long-running process may raise events occasionally and pass a percentage value to indicate the progress made. These additional pieces of information are known as event arguments and are contained within an instance of a class that is derived from EventArgs. In such a case, an appropriate EventArgs parameter will be declared in the delegate that supports the event.

EventHandler Delegate

Sometimes you will create events that have no requirement to provide additional status information; the event being raised will be enough. To simplify the declaration of such events, they can be linked to a delegate named EventHandler. This is a special delegate provided by the .NET framework.

The EventHandler delegate utilises two standard parameters. The first is used to identify the class that raised the event, the second is a simple EventArgs object that cannot contain any additional custom information. By using these two arguments, the convention for event parameters is maintained.

EventHandler Example

To demonstrate the use of the EventHandler delegate, we will create a class that is similar to the Car class created in the earlier article that described the use of events in C#. However, rather than creating a custom delegate we will use the one provided by the .NET framework. To begin, create a new console application and add a class named "Car". Add the following code to the Car class to create a property for a car's speed, an internal safety speed limit and an acceleration method:

private int _speed = 0;
private int _safetySpeed = 70;

public int Speed
{
    get
    {
        return _speed;
    }
}

public void Accelerate(int mph)
{
    int oldSpeed = _speed;
    _speed += mph;

    if (oldSpeed <= _safetySpeed && _speed > _safetySpeed)
    {
        OnSpeedLimitExceeded();
    }
}

Note the "OnSpeedLimitExceeded" method that is called by Accelerate when the speed limit is exceeded. This method provides the centralised point for raising the event. It will be marked as virtual so that any subclasses of Car will be able to override the event-raising functionality if required. We can now add this method to the Car class:

public virtual void OnSpeedLimitExceeded()
{
    if (SpeedLimitExceeded != null) SpeedLimitExceeded(this, EventArgs.Empty);
}

When the event is raised, two parameters are used. The first parameter will tell the subscribing method which object raised the event. The "this" keyword is used to indicate that the current instance was responsible for the action. As per the event argument convention, the second parameter is an instance of the EventArgs class. However, as we will be using the simple EventHandler delegate, there is no way to pass additional information so the EventArgs.Empty field is used to pass as empty object.

Finally, we need to declare the event and link it to the EventHandler delegate. This is achieved by adding the following line to the Car class:

public event EventHandler SpeedLimitExceeded;

Testing the Event

To test the event, modify the Program class to contain a functional Main method and a method that will be used in the event subscription as shown below. Execute the program to see the results.

static void Main(string[] args)
{
    Car car = new Car();
    car.SpeedLimitExceeded += new EventHandler(CarSpeedLimitExceeded);

    for (int i = 0; i < 3; i++)
    {
        car.Accelerate(30);
        Console.WriteLine("Speed: {0}mph", car.Speed);
    }
}

static void CarSpeedLimitExceeded(object source, EventArgs e)
{
    Car car = (Car)source;
    Console.WriteLine("Speed limit exceeded ({0}mph)", car.Speed);
}

/* OUTPUT

Speed: 30mph
Speed: 60mph
Speed limit exceeded (90mph)
Speed: 90mph

*/
3 March 2008