#383 – Removing a Handler from an Event

You can use the += operator to add a handler to an event.  Because an event can invoke multiple handlers, you can use the += operator to add additional handlers to the same event.  When the event is raised, all of the handlers will be called.

            kirby.Barked += kirby_Barked;
            kirby.Barked += kirby_Barked2;
        static void kirby_Barked(object o, EventArgs e)
        {
            Console.WriteLine("I see that Kirby barked");
        }

        static void kirby_Barked2(object o, EventArgs e)
        {
            Console.WriteLine("I ALSO see that Kirby barked");
        }


It’s also possible to remove a particular handler for the list of methods that an event will invoke, using the -= operator.

            kirby.Barked -= kirby_Barked;

#382 – Handling an Event that Returns Some Data

When you implement an event that returns data, you can use the EventHandler<TEventArgs> delegate type.

When you use the EventHandler<TEventArgs> delegate type, you define a new class that inherits from EventArgs.  A client that wants to handle the new event will need access to this new class.

Suppose that a Dog class implements a Barked event that has the following signature:

        public event EventHandler<BarkedEventArgs> Barked;

You would then add an event handler that accepts two parameters:

  • Parameter of type object, which references the object that raised the event
  • Parameter of type BarkedEventArgs, which contains the data the event wants to pass back

Here’s the complete example:

        static void Main()
        {
            Dog kirby = new Dog("Kirby");
            kirby.Barked += kirby_Barked;

            kirby.Bark("Grrr");
        }

        // Handle the Barked event
        static void kirby_Barked(object o, BarkedEventArgs e)
        {
            Console.WriteLine("Kirby barked: {0}", e.BarkSound);
        }

#381 – Implementing an Event that Returns Some Data

When you implement an event, you can define your own delegate type, or you can use the existing EventHandler or EventHandler<TEventArgs> types.

If you want your event to return some data, you should:

  • Create a new class that inherits from EventArgs for the event’s data
  • Use the EventHandler<TEventArgs> delegate type

Start by defining new EventArgs-based class that will store the event’s data.

    public class BarkedEventArgs : EventArgs
    {
        public string BarkSound { get; protected set; }
        public BarkedEventArgs(string barkSound)
        {
            BarkSound = barkSound;
        }
    }

Then, in your class, declare the event and a helper method to raise the event.

        // Declare the event
        public event EventHandler<BarkedEventArgs> Barked;

        // Helper method that raises the event
        protected virtual void OnBarked(string sound)
        {
            if (Barked != null)
                Barked(this, new BarkedEventArgs(sound));
        }

Finally, raise the event whenever a Dog barks.

        public void Bark(string barkSound)
        {
            Console.WriteLine(barkSound);

            OnBarked(barkSound);
        }

#380 – Handling Events that Use the EventHandler Delegate Type

Events that return no event data should normally use the built-in EventHandler delegate type.

        public event EventHandler Barked;

EventHandler is a delegate that takes two parameters.

public delegate void EventHandler(object o, EventArgs e);

The first parameter is assumed to be a reference to the object that raised the event.  The second parameter will contain a reference to some subclass of the EventArgs class, if the event does return data, or will be a null value, if the event does not pass data back.

Here’s an example of subscribing to the Barked event defined above.

            // Subscribing to the event
            Dog kirby = new Dog("Kirby");
            kirby.Barked += kirby_Barked;

            kirby.Bark();

And an example of a handler for the Barked event.

        static void kirby_Barked(object o, EventArgs e)
        {
            Console.WriteLine("Kirby barked");
        }

#379 – Using the EventHandler Delegate for Events that Return No Data

When you add an event to a class, you can use any delegate you like for the event’s type.  For example, you could based the event on a delegate that accepts a single parameter of type string:

        public delegate void StringHandlerDelegate(string s);
        public event StringHandlerDelegate Barked;

It’s recommended, however, that you use the one of the following two preexisting types as the delegate type:

  • EventHandler – for event that return no data
  • EventHandler<TEventArgs> – for event that returns some data

Below is an example of an event that returns no data.  The Dog.Barked event is raised when a Dog object barks.

        // Declare the event
        public event EventHandler Barked;

        // Helper method that raises the event
        protected virtual void OnBarked()
        {
            if (Barked != null)
                Barked(this, null);
        }

        // In Bark method, call helper to raise the event
        public void Bark()
        {
            Bark("Woof");
            OnBarked();
        }