I was looking through the C# Language Specification and bumped into the following explanations about Events section 1.7.5:
For a simple event declaration such as
public event EventHandler Click;
the compiler automatically provides the implementation underlying the += and -= operators.
An implementer who wants more control can get it by explicitly providing add and remove accessors. For example, the Button class could be rewritten as follows:
public class Button
{
private EventHandler handler;
public event EventHandler Click {
add { handler += value; }
remove { handler -= value; }
}
}
This change has no effect on client code, but allows the Button class more implementation flexibility. For example, the event handler for Click need not be represented by a field.
After reading this, I was like...cool! Let me play around and see what I can come up with. Like usual, I came up with the following code snippet:
using System;
namespace EventHandlerTest
{
///
/// Summary description for HandlerCaller.
///
class HandlerCaller
{
///
/// The main entry point for the application.
///
[STAThread]
static void Main(string[] args)
{
HandlerHost hh = new HandlerHost();
//Handlers for the 'main' events
EventHandler task1 = new EventHandler(HandlerCaller.HandleTask1);
EventHandler task2 = new EventHandler(HandlerCaller.HandleTask2);
//Add the handlers!
for(int i=0; i<10; i++)
hh.SomeEvent += (i%2 == 0) ? task1 : task2;
Console.WriteLine();
//Invoke the method
hh.DoTask();
Console.WriteLine();
//Remove the handlers!
for(int i=0; i<10; i++)
hh.SomeEvent -= (i%2 == 0) ? task1 : task2;
Console.WriteLine("Hit to continue...");
Console.ReadLine();
}
// Delegate #1 for the SomeEvent event
public static void HandleTask1(object sender, EventArgs e)
{
Console.WriteLine("From HandleTask1!!");
}
// Delegate #2 for the SomeEvent event
public static void HandleTask2(object sender, EventArgs e)
{
Console.WriteLine("From HandleTask2!!");
}
}
class HandlerHost
{
public HandlerHost()
{
// Register the events when they are done
EventHandlerAdded += new EventHandler(EventAdded);
EventHandlerRemoved += new EventHandler(EventRemoved);
}
EventHandler RegisteredHandlers;
event EventHandler EventHandlerAdded;
event EventHandler EventHandlerRemoved;
public event EventHandler SomeEvent
{
add
{
// We don't add the event here
// will handle this on the delegate
if(EventHandlerAdded != null)
EventHandlerAdded(value,null);
}
remove
{
// We don't remove the event here
// will handle this on the delegate
if(EventHandlerRemoved != null)
EventHandlerRemoved(value,null);
}
}
// Internal deleage for adding an event to class internal event list
void EventAdded(object sender, EventArgs e)
{
EventHandler eh = sender as EventHandler;
// Add the handler to the list!
RegisteredHandlers = Delegate.Combine(RegisteredHandlers,eh) as EventHandler;
// Report the console
Console.WriteLine("Added event mapped to method: {0}.{1}", eh.Method.DeclaringType.Name, eh.Method.Name);
}
// Internal delegate for removing an event from the class internal event list
void EventRemoved(object sender, EventArgs e)
{
EventHandler eh = sender as EventHandler;
// Remove the handler from the list!
RegisteredHandlers = Delegate.Remove(RegisteredHandlers,eh) as EventHandler;
// Report the console
Console.WriteLine("Removed event that was mapped to method: {0}.{1}", eh.Method.DeclaringType.Name, eh.Method.Name);
}
public void DoTask()
{
// We cannot call the event directly
// (like above since we are implementing the add and remove sections)
if(RegisteredHandlers != null)
RegisteredHandlers(this,null);
}
}
}
Happy coding!