Skip navigation

codeproject example

msdn tutorial / example

Modified msdn example, notes below

// events1.cs
using System;
using System.Collections;

namespace Example1
{
  // 1.  DECLARE A DELEGATE TYPE
  // that will be used to 
  public delegate void ChangedEventHandler( object sender, EventArgs e );



  public class ExtList : ArrayList
  {
    // 2.  DECLARE THE EVENT to be the type
    // of the delegate that you declared.
    public event ChangedEventHandler Changed;
    // An event IS an instance of a delegate
    // only several instances of the delegate
    // can be chained to execute in order.


    ///
    // Invoke the Changed event by explicitly
    // asking the Changed function to execute
    // (by a simple function call).
    protected virtual void OnChanged( EventArgs e )
    {
      if( Changed != null )
        Changed( this, e );
    }

    // Override some of the methods that can change the list;
    // invoke event after each
    public override int Add( object value )
    {
      int i = base.Add( value );

      // Trigger the OnChanged event.
      OnChanged( EventArgs.Empty );

      // This also could have been achieved by
      // simply invoking:
      //if( Changed != null )
      //  Changed( this, EventArgs.Empty ) ;
      // However the extra step above allows
      // a deriving class to actually add additional
      // functionality by overriding OnChanged
      // and then calling base.OnChanged( e ) when done.
      ////


      return i;
    }

    public override void Clear()
    {
      base.Clear();
      OnChanged( EventArgs.Empty );
    }

    public override object this[ int index ]
    {
      set
      {
        base[ index ] = value;
        OnChanged( EventArgs.Empty );
      }
    }
  }


  class Test
  {
    // This will be called whenever the list changes.
    private void ListChanged( object sender, EventArgs e )
    {
      Console.WriteLine( "This is called when the event fires." );
    }

    private void ListChanged2( object sender, EventArgs e )
    {
      Console.WriteLine( "SO WILL THIS, SUCKER." );
    }

    // Test the ExtList class.
    public static void Main()
    {
      // Create a new list.
      ExtList list = new ExtList();
      

      // Attach functions to execute.
      list.Changed += new ChangedEventHandler( list_Changed );
      list.Changed += new ChangedEventHandler( list_Changed2 );



      
      // Create a class that listens to the list's change event.
      Console.WriteLine("Adding an item");
      list.Add( "item 1" );
      
      // remove the first response function
      list.Changed -= new ChangedEventHandler( list_Changed ) ;


      Console.WriteLine( "Adding another item" ); 
      list.Add( "item 2" );
      

      list.Clear();
    }

    static void list_Changed2( object sender, EventArgs e )
    {
      Console.WriteLine( "INDEED IT HAS CHANGED!" );
    }

    static void list_Changed( object sender, EventArgs e )
    {
      Console.WriteLine( "THE LIST HAS CHANGED!" );
    }
  }
}

The point of event handlers is they are like a chain of functions that will execute in rapid succession on your command.

The msdn example is pretty good. In their example, they take a normal ArrayList and extend it with a Changed event. Now anytime the ArrayList is changed (through an addition, or a deletion, or totally clearing the list) the Changed event is TRIGGERED (basically, the Changed event is CALLED like a function would be), and so the SERIES of functions that were attached to the Changed event are executed immediately, in rapid succession. If there are no functions attached to the Changed event, then simply nothing happens.

What’s the difference between a C# event and just a normal function, you ask? Why can’t we just define a private function Changed() that executes on addition, on deletion, on clearing the list? WE COULD. But then we would have to MANUALLY provide some kind of List object that would be able to hold a series of delegates… it would just be more cumbersome.

But you are right. Events and event handlers don’t provide anything special above and beyond normal functions. The only thing good about them is how they provide a REALLY NICE mechanism to cause a set of functions to execute when certain things happen.

Creation of a custom event requires TWO things:

  1. A public delegate, which effectively specifies the type of function (argument list, return type) that can be chained onto the event
  2. Declaration of the event itself, inside the class that the event can “happen to”

The above two items look like this:

// Declare the delegate outside so any class can see it:
public delegate void ChangedEventHandler( object sender, EventArgs e );

public class ExtList : ArrayList
{
// DECLARE THE EVENT to be the type
// of the delegate that you want to be
// “attachable” this event.
public event ChangedEventHandler Changed;

// the WHOLE POINT of this “Changed” variable
// is that it will be like a queue that can accept
// a series of ChangedEventHandler objects
// (which are really going to be references to functions!)
}

So again, an event … is like a CHAIN OF FUNCTIONS.

A programmer attaches ANY NUMBER of functions to line up for execution simply by using += syntax:

class Test
{
// This will be called whenever the list changes.
private void ListChanged( object sender, EventArgs e )
{
Console.WriteLine( “This is called when the event fires.” );
}

private void ListChanged2( object sender, EventArgs e )
{
Console.WriteLine( “SO WILL THIS, SUCKER.” );
}

// Test the ExtList class.
public static void Main()
{
// Create a new list.
ExtList list = new ExtList();

// Attach functions to execute.
list.Changed += new ChangedEventHandler( list_Changed );
list.Changed += new ChangedEventHandler( list_Changed2 );

// now trigger their execution by adding an item:
Console.WriteLine(“Adding an item”);
list.Add( “item 1” ); // we see output from BOTH ListChanged
// and ListChanged2(), in the order that we attached them.
}
}

So in the above, WHEN list.Changed() gets EXECUTED, what will automatically happen is, list_Changed (which is a function) will execute first, followed by list_Changed2.

OK OK, so now HOW DID WE TRIGGER THE EVENT TO FIRE?

You trigger execution of that “queue” of functions (first one chained on gets executed first.. all the way to the last one you chained on there) by INVOKING THE NAME OF THE event:

Changed() ;

HOWEVER, CALLS TO YOUR event MUST BE WITHIN THE CLASS IN WHICH THE event IS DEFINED

So, re-emphasizing this point:

Changed() ;

CANNOT BE CALLED OUTSIDE THE CLASS. This is when you get an error of the form

Error 1 The event ‘Example1.ExtList.Changed’ can only appear on the left hand side of += or -= (except when used from within the type ‘Example1.ExtList’)

The whole thing about “appearing only on the left hand side of += or -=” is that, TO EXTERNAL CLASSES, an event CANNOT BE DIRECTLY INVOKED.

An EVENT, what constitutes FIRING of that event is meant to be completely INTERNAL to the class that declares the event. Any public function of the class may fire the event, but code from outside the class MAY NEVER invoke the event directly (unless you actually provide a public function, that all it does, is invoke the event). There is an example of this in System.Windows.Forms.Button: button1.PerformClick(). All it does is invoke the Click event handler, which you are NOT free to do because you are NOT inside the Button class, ever.

What you’re supposed to do is provide “ins” to allow the event to be invoked.. a public function that, upon invokation, will FIRE the event.

The user of your class isn’t really supposed to think about FIRING the event though. They’re supposed to use your class like normal.. and when certain things happen (something was added to the list), the Changed() event, in this example, fires as a kind of SIDE EFFECT.

If a class does not expose a function to trigger an event, then you simply cannot cause that event to trigger yourself, unless you inherit that class and write a function in the derived class that invokes the event.

Whew. That is all I have to say about events.

Advertisements

One Trackback/Pingback

  1. By Simple C# events example « Bobobobo’s Weblog on 02 Jun 2009 at 11:31 pm

    […] in misc OK, this one is a bit more complex, so start here, then go […]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: