Custom EventArgs

In previous examples of raising events, the event was raised using an blank EventArgs object. When there is no data to report about an event, an EventArgs instance is still required because the EventHandler delegate requires an argument for the EventArgs parameter.

When your event requires data to send back to the handling method, you will need to define your own EventArgs type.

C#
/// <summary>
/// Represents event data for a grade average below failure.
/// </summary>
public class AverageBelowFailEventArgs : EventArgs
{
    /// <summary>
    /// Gets the difference between the grade average and the fail mark.
    /// </summary>
    public double BelowAverageDifference
    {
        get;
    }

    /// <summary>
    /// Initializes a new instance of the AverageBelowFailEventArgs class.
    /// </summary>
    /// <param name="belowAverageDifference">The difference between the grade average and the fail mark.</param>
    public AverageBelowFailEventArgs(double belowAverageDifference)
    {
        this.BelowAverageDifference = belowAverageDifference;
    }
}

The Student class would be updated to:

C#
public class Student
{
    public event EventHandler<AverageBelowFailEventArgs> AverageBelowFail;

    public void AddTestMark(double mark)
    {
        if (mark < 0 || mark > 1)
            throw new ArgumentOutOfRangeException("mark", "The mark must be a value of zero or greater.");

        const double PassingGrade = .65;
        const int MinimumNumberOfTests = 3;        

        this.NumberOfTests++;
        this.SumOfTests += mark;

        double testAverage = this.SumOfTests / this.NumberOfTests;

        if(this.NumberOfTest > MinimumNumberOfTests && testAverage < PassingGrade)
        {
            OnAverageBelowFail(new AverageBelowFailEventArgs(PassingGrade - average));
        }
    }

    protected virtual void OnAverageBelowFail(AverageBelowFailEventArgs eventArgs)
    {
        if(AverageBelowFail != null)
        {
            AverageBelowFail(this, eventArgs);
        }
    }
}

When the event AverageBelowFail is declared, the delegate type EventHandler is indicated with a generic, where the generic type is the custom EventArg type AverageBelowFailEventArgs. When the event is raised, by calling the "On" method, a new instance of the AverageBelowFailEventArgs class is instantiated and is used as an argument for the call to the "On" method. The implementation of the "On" method uses the AverageBelowFailEventArgs instance when calling the handler method.

The event handler method would would declare the parameter e as the EventArgs type AverageBelowFailEventArgs.

C#
static void Student_AverageBelowFail(object sender, AverageBelowFailEventArgs e)
{
    Console.WriteLine("ALERT! Your test average is {0:P} below the standard.", e.BelowAverageDifference);
}

The e parameter can then be used to access data about what happened during the event.