#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();
        }

#378 – Implementing an Event

You can subscribe to an event in a class by writing an event handler.  You can also implement events in your own class.

An event is just a class member that is an instance of a delegate type and is declared using the event keyword.

Suppose you’ve defined a delegate type that takes a string parameter:

    public delegate void StringHandlerDelegate(string s);

You can now use this delegate type to define an event in a class.  The event is just an instance of the delegate type.

        public event StringHandlerDelegate Barked;

You can now add code in your class to raise the event. We fire the Barked event from the Bark method.

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

            // Raise the event
            if (Barked != null)
                Barked(barkSound);
        }

Before invoking the delegate, we make sure it’s not null, to avoid an exception at run-time.

#370 – Subscribe to an Event by Adding an Event Handler

You subscribe to a particular event in C# by defining an event handler–code that will be called whenever the event occurs (is raised). You then attach your event handler to an event on a specific object, using the += operator.

Below is an example where we define an event handler for the Dog.Barked event.  Each time that Kirby barks, we’ll record the date and time of the bark in a list.

        private static List<DateTime> barkLog = new List<DateTime>();

        static void Main()
        {
            Dog kirby = new Dog("Kirby", 12);

            kirby.Barked += new EventHandler(kirby_Barked);

            kirby.Bark();
            Console.ReadLine();

            kirby.Bark();
            Console.ReadLine();
        }

        // Neither argument is used, for the moment
        static void kirby_Barked(object sender, EventArgs e)
        {
            // Log Kirby's barks
            barkLog.Add(DateTime.Now);
        }

Assuming that the Dog class fires its Barked event whenever we call the Bark method, our handler will get called whenever Kirby barks.

#369 – Multiple Clients Can Subscribe to the Same Event

An event in C# is a mechanism that allows an object to inform client code about something that happened inside the object that the other code might care about.

It’s often the case that there are several different pieces of client code that care about the same event.  In other words, when an object raises an event, there may be one subscriber listening for the event, no subscribers, or many subscribers.

Here’s an example that shows two subscribers to the same Dog.Barked event.

#368 – How Events Work

An event in C# is a mechanism that allows an object to inform client code about something that happened inside the object that the other code might care about.

For example, you might have a Dog object that raises a Barked event whenever someone calls the dog’s Bark method.  Your code can be notified whenever the dog barks.

In .NET, we say that the Dog object raises the Barked eventThe logging code handles the Barked event in a method known as an event handler.

Events in C# implement something known as the Publish/Subscribe pattern.  The Dog class publishes information about when the dog barks and the logging code subscribes to that information. 

This is also known as the Observer pattern.  The logging code observes the Dog object and the Dog object notifies any observers whenever the dog barks.

Follow

Get every new post delivered to your Inbox.

Join 43 other followers