May 14, 2010

Events In C#

Look here: How to: Implement Events in Your Class - A good beginners guide.
and here: C# events vs. delegates - Good detailed explanation of events and how they differ from delegates

Implementing the event in Your Publisher Class

Step 1 (Optional): Define your custom "EventArgs" class
public class SomethingChangedEventArgs : EventArgs
{
...
}
The following steps take place in the event publisher class
class SomethingChangedEventPublisher
{
Step 2: Expose your custom EventHandler
  public event EventHandler<SomethingChangedEventArgs> SomethingChanged; // for events with custom arguments
  public event EventHandler SomethingChanged; // otherwise use this for standard events
Step 3: Define an event publishing helper method (this is agood practice)
  void PublishSomethingChangedEvent(SomethingChangedEventArgs ea)
  {
    EventHandler<SomethingChangedEventArgs> eh = this.SomethingChanged
    if (eh != null)
      eh(this, ea);
  }
Step 4: Publish/Fire/Trigger the event in the appropriate places
  ...
  PublishSomethingChangedEvent(this, new SomethingChangedEventArgs(...));
  
  ...
}

Subscribing to the event in the Listener/Observer/Subscriber Class

The following steps take place in the event observer/subscriber class
class SomethingChangedEventSubscriber
{
Step 5: Subscribe to the event
  // VS Intellisense will do most of the work for you here!
  SomethingChangedEventSource.SomethingChanged += new EventHandler<SomethingChangedEventArgs>(OnSomethingChanged);
...
Step 6: Handle the event
  // The method where the SomethingChangedEvent is processed 
  private void OnSomethingChanged(object sender, SomethingChangedEventArgs eargs)
  {
    // SomethingChanged detected, now do something with it here
  }
...
Step 7: Unsubscribe to the event. This is in my experience the biggest cause of memory leaks in C# programs
  // VS Intellisense will do most of the work for you here!
  SomethingChangedEventSource.SomethingChanged -= new EventHandler<SomethingChangedEventArgs>(OnSomethingChanged);
  
...
}
Alternatively, use an inline delegate to handle the event
SomethingChangedEventSource.SomethingChanged += delegate (object sender, SomethingChangedEventArgs e)
{
  ...
};
But there is a danger to doing this see here
Also in Windows Forms programs events often lead to memory leaks as the events were never detached seehere
Note that the event source is called the "Event Publisher", ie. it is the class containg the event definition. The event target or "Subscriber" is the object attaching a delegate to the event. Be careful with C# events and the Garbage Collection of unreferenced objects. A C# event publisher holds a reference to the subscriber so the Subscriber cannot be disposed of until that event is detached (or there is no longer a reference to either the publisher or subscriber). This also means that if the subscriber has a Dispose event, you cannot rely on the system to invoke it in a GC round until that event is detached. If you attach a subscriber on to the event of a publisher, ensure it is detached

No comments: