#386 – Implementing a Static Event

You can implement static events in the same way that you implement normal (instance) events.  Like other static members, static events are associated with the class itself, rather than with an instance of the class.

An implementation of a static event (assumes existence of SomebodyBarkedEventArgs class):

        public static event EventHandler<SomebodyBarkedEventArgs> SomebodyBarked;

        // In instance method, raise the static event
        public void Bark(string barkSound)
        {
            Console.WriteLine("{0} says {1}", Name, barkSound);

            if (Dog.SomebodyBarked != null)
                Dog.SomebodyBarked(null, new SomebodyBarkedEventArgs(Name, barkSound));
        }

Adding an event handler for this event:

        static void Main()
        {
            // Tell me when any dog barks
            Dog.SomebodyBarked += new EventHandler<SomebodyBarkedEventArgs>(Dog_SomebodyBarked);

            Dog kirby = new Dog("Kirby");
            Dog jack = new Dog("Jack");

            // Pesky dogs bark
            jack.Bark("Grrrr");
            kirby.Bark("Woof");
        }

        static void Dog_SomebodyBarked(object sender, SomebodyBarkedEventArgs e)
        {
            Console.WriteLine("Dog {0} barked, saying {1}", e.DogName, e.Bark);
        }

Advertisements

#384 – The Difference Between Delegates and Events

Delegates are not the same thing as events in C#.

Delegates

  • A delegate type defines a signature for a method (number and type of parameters and return type)
  • A delegate instance is an instance of a delegate type that can refer to one or more methods
  • Can add/remove handlers using the +=, -= operators
  • Can invoke handlers by calling delegate instance like a method

Events

  • Is a class member representing something that the class might notify calling code about
  • Declared in the class like a field, whose type is a delegate type
  • Wraps a private member variable that is a delegate instance
  • Wraps private methods that add/remove methods to the delegate instance’s invocation list
  • Client code can add/remove handlers using the +=, -= operators
  • Client code can’t invoke directly

Basically, an event is a mechanism that uses a delegate to notify client code of something without exposing the delegate’s invocation list to the client.

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