| Content
          
          
          
            Call a Function directly - No
            DelegateThe very basic Delegate
 Calling Static Functions
 Calling Member Functions
 Multicasting
 
            ConventionsSimple Event
 The Second Change Event
            Example
 
 
          All of us have been exposed to event driven programming of
          some sort or the other. C# adds on value to the often mentioned world of event driven
          programming by adding support through events and delegates. The emphasis of this
          article would be to identify what exactly happens when you add an event handler to your
          common UI controls. A simple simulation of what could possibly be going on behind the
          scenes when the AddOnClick or any similar event is added to the Button class will be
          explained. This will help you understand better the nature of event handling using multi
          cast delegates. 
          A delegate in C# is similar to a function pointer in C or C++.
          Using a delegate allows the programmer to encapsulate a reference to a method inside a
          delegate object. The delegate object can then be passed to code which can call the
          referenced method, without having to know at compile time which method will be
          invoked. Call a
        Function directly - No Delegate 
          In most cases, when we call a function, we specify the function to
          be called directly. If the class MyClass has a function
          named Process, we'd normally call it like this (SimpleSample.cs): using System;
 namespace Akadia.NoDelegate
 {
 public class MyClass
 {
 public void Process()
 {
 Console.WriteLine("Process() begin");
 Console.WriteLine("Process() end");
 }
 }
 
 public class Test
 {
 static void Main(string[] args)
 {
 MyClass myClass = new MyClass();
 myClass.Process();
 }
 }
 }
 That works well in most situations. Sometimes, however, we don't
          want to call a function directly - we'd like to be able to pass it to somebody else so
          that they can call it. This is especially useful in an event-driven system such as a
          graphical user interface, when I want some code to be executed when the user clicks on a
          button, or when I want to log some information but can't specify how it is
          logged. The very basic
        Delegate 
          An interesting and useful property of a delegate is that it does
          not know or care about the class of the object that it references. Any object will do;
          all that matters is that the method's argument types and return type match the
          delegate's. This makes delegates perfectly suited for "anonymous" invocation. The signature of a single cast delegate is shown below: delegate result-type identifier
          ([parameters]); where: 
            result-type: The result type, which matches the return type of
            the function.identifier: The delegate name.parameters: The Parameters, that the function takes. Examples: 
            
              | public delegate void SimpleDelegate
                () This declaration defines a delegate named
                SimpleDelegate, which will encapsulate any method
                that takesno parameters and returns no value.
 |  
              | public delegate int ButtonClickHandler
                (object obj1, object obj2) This declaration defines a delegate
                named ButtonClickHandler, which will encapsulate
                any method that takestwo objects as parameters and returns an int.
 |  A delegate will allow us to specify what the function we'll be
          calling looks like without having to specify which function to call.
          The declaration for a delegate looks just like the declaration for a function, except
          that in this case, we're declaring the signature of functions that this delegate can
          reference. There are three steps in defining and using delegates: 
            DeclarationInstantiationInvocation A very basic example (SimpleDelegate1.cs): using System;
 namespace Akadia.BasicDelegate
 {
 // Declaration
 public delegate void SimpleDelegate();
 
 class TestDelegate
 {
 public static void MyFunc()
 {
 Console.WriteLine("I
          was called by delegate ...");
 }
 
 public static void Main()
 {
 // Instantiation
 SimpleDelegate simpleDelegate = new SimpleDelegate(MyFunc);
 
 // Invocation
 simpleDelegate();
 }
 }
 }
 Compile an test: # csc SimpleDelegate1.cs# SimpleDelegate1.exe
 I was called by delegate
          ...
 Calling Static
        Functions 
          For our next, more advanced example (SimpleDelegate2.cs), declares a delegate that takes a single string
          parameter and has no return type: using System;
 namespace Akadia.SimpleDelegate
 {
 // Delegate Specification
 public class MyClass
 {
 // Declare a delegate
          that takes a single string parameter
 // and has no return type.
 public delegate void LogHandler(string message);
 
 // The use of the
          delegate is just like calling a function directly,
 // though we need to add a check to see if the
          delegate is null
 // (that is, not pointing to a function)
          before calling the function.
 public void Process(LogHandler logHandler)
 {
 if (logHandler !=
          null)
 {
 logHandler("Process() begin");
 }
 
 if (logHandler !=
          null)
 {
 logHandler ("Process() end");
 }
 }
 }
 
 // Test Application to use the defined
          Delegate
 public class TestApplication
 {
 // Static Function: To which is used in the Delegate. To call the
          Process()
 // function, we need to declare a logging
          function: Logger() that matches
 // the signature of the
          delegate.
 static void Logger(string s)
 {
 Console.WriteLine(s);
 }
 
 static void Main(string[] args)
 {
 MyClass myClass = new
          MyClass();
 
 // Crate an instance of the delegate, pointing to the logging function.
 // This delegate will
          then be passed to the Process() function.
 MyClass.LogHandler myLogger = new
          MyClass.LogHandler(Logger);
 myClass.Process(myLogger);
 }
 }
 }
 Compile an test: # csc SimpleDelegate2.cs# SimpleDelegate2.exe
 Process() begin
 Process() end
 Calling Member
        Functions 
          In the simple example above, the Logger( ) function
          merely writes the string out. A different function might want to log the information to a
          file, but to do this, the function needs to know what file to write the information to
          (SimpleDelegate3.cs) using System;using System.IO;
 
 namespace Akadia.SimpleDelegate
 {
 // Delegate Specification
 public class MyClass
 {
 // Declare a delegate
          that takes a single string parameter
 // and has no return type.
 public delegate void LogHandler(string message);
 
 // The use of the
          delegate is just like calling a function directly,
 // though we need to add a check to see if the
          delegate is null
 // (that is, not pointing to a function)
          before calling the function.
 public void Process(LogHandler logHandler)
 {
 if (logHandler !=
          null)
 {
 logHandler("Process() begin");
 }
 
 if (logHandler !=
          null)
 {
 logHandler ("Process() end");
 }
 }
 }
 
 // The FileLogger class merely encapsulates the
          file I/O
 public class FileLogger
 {
 FileStream fileStream;
 StreamWriter streamWriter;
 
 //
          Constructor
 public FileLogger(string filename)
 {
 fileStream = new
          FileStream(filename, FileMode.Create);
 streamWriter = new
          StreamWriter(fileStream);
 }
 
 // Member
          Function which is used in the Delegate
 public void Logger(string s)
 {
 streamWriter.WriteLine(s);
 }
 
 public void Close()
 {
 streamWriter.Close();
 fileStream.Close();
 }
 }
 
 // Main() is modified so that the delegate
          points to the Logger()
 // function on the fl instance of a FileLogger. When this delegate
 // is invoked from Process(), the member function is called and
 // the string is logged to the appropriate file.
 public class TestApplication
 {
 static void Main(string[] args)
 {
 FileLogger fl = new
          FileLogger("process.log");
 
 MyClass myClass = new
          MyClass();
 
 // Crate an instance of the delegate, pointing to the Logger()
 // function on the fl
          instance of a FileLogger.
 MyClass.LogHandler myLogger = new
          MyClass.LogHandler(fl.Logger);
 myClass.Process(myLogger);
 fl.Close();
 }
 }
 }
 The cool part here is that we didn't have to change the Process()
          function; the code to all the delegate is the same regardless of whether it refers to a
          static or member function. Compile an test: # csc SimpleDelegate3.cs# SimpleDelegate3.exe
 # cat process.log
 Process() begin
 Process() end
 Multicasting 
          Being able to point to member functions is nice, but
          there are more tricks you can do with delegates. In C#, delegates are
          multicast, which means that they can point to more than one function at
          a time (that is, they're based off the System.MulticastDelegate type). A multicast
          delegate maintains a list of functions that will all be called when the delegate is
          invoked. We can add back in the logging function from the first example, and call both
          delegates. Here's what the code looks like: using System;using System.IO;
 
 namespace Akadia.SimpleDelegate
 {
 // Delegate Specification
 public class MyClass
 {
 // Declare a delegate
          that takes a single string parameter
 // and has no return type.
 public delegate void LogHandler(string message);
 
 // The use of the
          delegate is just like calling a function directly,
 // though we need to add a check to see if the
          delegate is null
 // (that is, not pointing to a function)
          before calling the function.
 public void Process(LogHandler logHandler)
 {
 if (logHandler !=
          null)
 {
 logHandler("Process() begin");
 }
 
 if (logHandler !=
          null)
 {
 logHandler ("Process() end");
 }
 }
 }
 
 // The FileLogger class merely encapsulates the
          file I/O
 public class FileLogger
 {
 FileStream fileStream;
 StreamWriter streamWriter;
 
 //
          Constructor
 public FileLogger(string filename)
 {
 fileStream = new
          FileStream(filename, FileMode.Create);
 streamWriter = new
          StreamWriter(fileStream);
 }
 
 // Member Function
          which is used in the Delegate
 public void Logger(string s)
 {
 streamWriter.WriteLine(s);
 }
 
 public void Close()
 {
 streamWriter.Close();
 fileStream.Close();
 }
 }
 
 // Test
          Application which calls both Delegates
 public class TestApplication
 {
 // Static Function which is used in the
          Delegate
 static void Logger(string s)
 {
 Console.WriteLine(s);
 }
 
 static void Main(string[] args)
 {
 FileLogger fl = new
          FileLogger("process.log");
 
 MyClass myClass = new
          MyClass();
 
 // Crate an instance of the delegates, pointing to the static
 // Logger() function
          defined in the TestApplication class and
 // then to member
          function on the fl instance of a FileLogger.
 MyClass.LogHandler
          myLogger = null;
 myLogger += new MyClass.LogHandler(Logger);
 myLogger += new MyClass.LogHandler(fl.Logger);
 
 myClass.Process(myLogger);
 fl.Close();
 }
 }
 }
 
 Compile an test: # csc SimpleDelegate4.cs# SimpleDelegate4.exe
 Process() begin
 Process() end
 # cat process.log
 Process() begin
 Process() end
 
          The Event model in C# finds its roots in the event
          programming model that is popular in asynchronous programming. The basic foundation
          behind this programming model is the idea of "publisher and subscribers." In this model,
          you have publishers who will do some logic and publish an "event."
          Publishers will then send out their event only to subscribers who have
          subscribed to receive the specific event. In C#, any object can publish a set of events
          to which other applications can subscribe. When the publishing class raises an
          event, all the subscribed applications are notified. The following figure shows this
          mechanism. 
 Conventions 
          The following important conventions are used with
          events: 
            Event Handlers in the .NET Framework return void and take two
            parameters.The first paramter is the source of the event; that is the
            publishing object.The second parameter is an object derived from
            EventArgs.Events are properties of the class publishing the
            event.The keyword event controls how the event property is accessed by
            the subscribing classes. Simple Event 
          Let's modify our logging example from above to use
          an event rather than a delegate: using System;using System.IO;
 
 namespace Akadia.SimpleEvent
 {
 /* =========
          Publisher of the Event ============== */
 public class MyClass
 {
 // Define a delegate
          named LogHandler, which will encapsulate
 // any method that takes a string as the
          parameter and returns no value
 public delegate void LogHandler(string message);
 
 // Define an
          Event based on the above Delegate
 public event
          LogHandler Log;
 
 // Instead of having the
          Process() function take a delegate
 // as a parameter, we've declared a Log event.
          Call the Event,
 // using the OnXXXX Method, where XXXX is the
          name of the Event.
 public void Process()
 {
 OnLog("Process() begin");
 OnLog("Process() end");
 }
 
 // By Default, create an
          OnXXXX Method, to call the Event
 protected void OnLog(string message)
 {
 if (Log != null)
 {
 Log(message);
 }
 }
 }
 
 // The FileLogger class merely encapsulates the
          file I/O
 public class FileLogger
 {
 FileStream fileStream;
 StreamWriter streamWriter;
 
 //
          Constructor
 public FileLogger(string filename)
 {
 fileStream = new
          FileStream(filename, FileMode.Create);
 streamWriter = new
          StreamWriter(fileStream);
 }
 
 // Member Function which
          is used in the Delegate
 public void Logger(string s)
 {
 streamWriter.WriteLine(s);
 }
 
 public void Close()
 {
 streamWriter.Close();
 fileStream.Close();
 }
 }
 
 /* ========= Subscriber of the Event ============== */
 // It's now easier and
          cleaner to merely add instances
 // of the delegate to the event, instead of having to
 // manage things ourselves
 public class TestApplication
 {
 static void Logger(string s)
 {
 Console.WriteLine(s);
 }
 
 static void Main(string[] args)
 {
 FileLogger fl = new
          FileLogger("process.log");
 MyClass myClass =
          new MyClass();
 
 // Subscribe the Functions Logger and fl.Logger
 myClass.Log += new
          MyClass.LogHandler(Logger);
 myClass.Log += new
          MyClass.LogHandler(fl.Logger);
 
 // The Event will now be triggered in the Process()
          Method
 myClass.Process();
 
 fl.Close();
 }
 }
 }
 Compile an test: # csc SimpleEvent.cs# SimpleEvent.exe
 Process() begin
 Process() end
 # cat process.log
 Process() begin
 Process() end
 The Second
        Change Event Example 
          Suppose you want to create a Clock class that uses
          events to notify potential subscribers whenever the local time changes value by one
          second. Here is the complete, documented example: using System;using System.Threading;
 
 namespace SecondChangeEvent
 {
 /* ======================= Event Publisher
          =============================== */
 
 // Our subject -- it is this class that other
          classes
 // will observe. This class publishes one event:
 // SecondChange. The observers subscribe to that event.
 public class Clock
 {
 // Private Fields holding the hour,
          minute and second
 private int _hour;
 private int _minute;
 private int _second;
 
 // The delegate named
          SecondChangeHandler, which will encapsulate
 // any method that takes a clock object and a
          TimeInfoEventArgs
 // object as the parameter and returns no value. It's
          the
 // delegate the subscribers must implement.
 public delegate void SecondChangeHandler (
 object clock,
 TimeInfoEventArgs timeInformation
 );
 
 // The event we publish
 public event SecondChangeHandler SecondChange;
 
 // The method which fires the
          Event
 protected void OnSecondChange(
 object clock,
 TimeInfoEventArgs timeInformation
 )
 {
 // Check if there are any
          Subscribers
 if (SecondChange != null)
 {
 // Call the Event
 SecondChange(clock,timeInformation);
 }
 }
 
 // Set the clock running, it will
          raise an
 // event for each new second
 public void Run()
 {
 for(;;)
 {
 // Sleep 1 Second
 Thread.Sleep(1000);
 
 // Get the current time
 System.DateTime dt =
          System.DateTime.Now;
 
 // If the second has changed
 // notify the
          subscribers
 if (dt.Second !=
          _second)
 {
 // Create the TimeInfoEventArgs object
 //
          to pass to the subscribers
 TimeInfoEventArgs timeInformation =
 new TimeInfoEventArgs(
 dt.Hour,dt.Minute,dt.Second);
 
 // If anyone has subscribed, notify them
 OnSecondChange (this,timeInformation);
 }
 
 // update the state
 _second =
          dt.Second;
 _minute =
          dt.Minute;
 _hour = dt.Hour;
 
 }
 }
 }
 
 // The class to hold the information about the
          event
 // in this case it will hold only information
 // available in the clock class, but could hold
 // additional state information
 public class TimeInfoEventArgs : EventArgs
 {
 public TimeInfoEventArgs(int hour, int minute, int
          second)
 {
 this.hour = hour;
 this.minute = minute;
 this.second = second;
 }
 public readonly int hour;
 public readonly int minute;
 public readonly int second;
 }
 
 /* ======================= Event Subscribers
          =============================== */
 
 // An observer. DisplayClock subscribes to the
 // clock's events. The job of DisplayClock is
 // to display the current time
 public class DisplayClock
 {
 // Given a clock, subscribe to
 // its SecondChangeHandler event
 public void Subscribe(Clock theClock)
 {
 theClock.SecondChange +=
 new
          Clock.SecondChangeHandler(TimeHasChanged);
 }
 
 // The method that implements
          the
 // delegated functionality
 public void TimeHasChanged(
 object theClock, TimeInfoEventArgs
          ti)
 {
 Console.WriteLine("Current Time:
          {0}:{1}:{2}",
 ti.hour.ToString(),
 ti.minute.ToString(),
 ti.second.ToString());
 }
 }
 
 // A second subscriber whose job is to write to a
          file
 public class LogClock
 {
 public void Subscribe(Clock theClock)
 {
 theClock.SecondChange +=
 new
          Clock.SecondChangeHandler(WriteLogEntry);
 }
 
 // This method should write to a
          file
 // we write to the console to see the effect
 // this object keeps no
          state
 public void WriteLogEntry(
 object theClock, TimeInfoEventArgs
          ti)
 {
 Console.WriteLine("Logging to file:
          {0}:{1}:{2}",
 ti.hour.ToString(),
 ti.minute.ToString(),
 ti.second.ToString());
 }
 }
 
 /* ======================= Test Application
          =============================== */
 
 // Test Application which implements the
 // Clock Notifier - Subscriber Sample
 public class Test
 {
 public static void Main()
 {
 // Create a new
          clock
 Clock theClock = new Clock();
 
 // Create the
          display and tell it to
 // subscribe to the clock just
          created
 DisplayClock dc = new
          DisplayClock();
 dc.Subscribe(theClock);
 
 // Create a Log
          object and tell it
 // to subscribe to the clock
 LogClock lc = new LogClock();
 lc.Subscribe(theClock);
 
 // Get the clock
          started
 theClock.Run();
 }
 }
 }
 
          The Clock class from the last sample could simply print the time
          rather tahn raising an event, so why bother with the introduction of using
          delegates? The advantage of the publisg / subscribe idiom is that any number of
          classes can be notified when an event is raised. The subscribing classes do not need
          to know how the Clock works, and the Clock does not need to know what they are going to
          do in response to the event. Similarly a button can publish an Onclick event, and any
          number of unrelated objects can subscribe to that event, receiving notification when the
          button is clicked. The publisher and the subscribers are decoupled by the
          delegate. This is highly desirable as it makes for more flexible and robust
          code. The clock can chnage how it
          detects time without breaking any of the subscribing classes. The subscribing classes can
          change how they respond to time
          changes without breaking the Clock.
          The two classes spin indepentdently of one another, which makes for code that is easier
          to maintain. |