Click here to Skip to main content
Click here to Skip to main content

Tagged as

Anonymous methods as event handlers – Part 1

, 1 Sep 2009
Rate this:
Please Sign up or sign in to vote.
The syntactic sugar offered by anonymous methods makes them great candidates for writing event handlers; together with smart type inference, they reduce the amount of code written by an order of magnitude. And that’s without considering the power offered by closures. With event handlers, closures a

The syntactic sugar offered by anonymous methods makes them great candidates for writing event handlers; together with smart type inference, they reduce the amount of code written by an order of magnitude.

And that’s without considering the power offered by closures. With event handlers, closures allow you to kind of “stuff” extra parameters into the handler, without changing the actual number of formal parameters. This blog post shows a situation where an anonymous method acting as an event handler makes code simpler, and then goes on to show a gotcha with un-subscription and anonymous methods.

Here’s a simple Control class that fires a bunch of events.

   1: public void Initialize()
   2: {
   3:     control.KeyPressed += IfEnabledThenDo(control_KeyPressed);
   4:     control.MouseMoved += IfEnabledThenDo(control_MouseMoved);
   5: }
   6:  
   7: public void Destroy()
   8: {
   9:     control.KeyPressed -= IfEnabledThenDo(control_KeyPressed);
  10:     control.MouseMoved -= IfEnabledThenDo(control_MouseMoved);
  11: }

Let’s say you’re developing a GUI application with this class, and you want to handle events only if the originating control is visually enabled i.e., Enabled set to true. Pretty reasonable constraint, but tedious to implement, if you go the standard way of adding the check to the start of each of your event handlers.

   1: class GUIApp
   2: {
   3:     public void Initialize()
   4:     {
   5:         Control control = new Control();
   6:         control.KeyPressed += new EventHandler<control.controleventargs />(control_KeyPressed);
   7:         control.MouseMoved += new EventHandler<control.controleventargs />(control_MouseMoved);
   8:     }
   9:  
  10:     void control_MouseMoved(object sender, Control.ControlEventArgs e)
  11:     {
  12:         if (e.Control.Enabled)
  13:         {
  14:             /// 
  15:         }
  16:     }
  17:  
  18:     void control_KeyPressed(object sender, Control.ControlEventArgsEventArgs e)
  19:     {
  20:         if (e.Control.Enabled)
  21:         {
  22:             ///
  23:         }
  24:     }
  25: }
With an anonymous method, you could write a far more terse and easy to maintain version
   1: class GUIApp
   2: {
   3:     public void Initialize()
   4:     {
   5:         Control control = new Control();
   6:         control.KeyPressed += IfEnabledThenDo(control_KeyPressed);
   7:         control.MouseMoved += IfEnabledThenDo(control_MouseMoved);
   8:     }
   9:  
  10:     public EventHandler<control.controleventargs /> IfEnabledThenDo(EventHandler<control.controleventargs /> actualAction)
  11:     {
  12:         return (sender, args) => { if (args.Control.Enabled) { actualAction(sender, args); } };
  13:     }
  14:  
  15:     void control_MouseMoved(object sender, Control.ControlEventArgs e)
  16:     {
  17:         ///
  18:     }
  19:  
  20:     void control_KeyPressed(object sender, Control.ControlEventArgs e)
  21:     {
  22:         ///
  23:     }
  24: }

IfEnabledThenDo returns an anonymous function that first checks whether the control is enabled before calling the actual function. The code is much shorter, and the condition is checked only in one place, which makes it easy to modify or add additional logic without having to remember to change every single event handler. Plus, the reads like an English statement – subscribe to the event and if enabled, then do whatever else is necessary.

Great, but unless you are a masochist who revels in littering the code base with hard to reproduce bugs that bomb your app only when demoing to your most important customer, you must, of course, write code to unsubscribe. But there’s no method name to refer to, so you do it the same way as you did when subscribing.

   1: public void Initialize()
   2: {
   3:     control.KeyPressed += IfEnabledThenDo(control_KeyPressed);
   4:     control.MouseMoved += IfEnabledThenDo(control_MouseMoved);
   5: }
   6:  
   7: public void Destroy()
   8: {
   9:     control.KeyPressed -= IfEnabledThenDo(control_KeyPressed);
  10:     control.MouseMoved -= IfEnabledThenDo(control_MouseMoved);
  11: }

This, unfortunately, won’t work – the application will still remain subscribed to those events. Can you figure out why?

Answer and more in the next blog post.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

S. Senthil Kumar
Software Developer Atmel R&D India Pvt. Ltd.
India India
I'm a 27 yrs old developer working with Atmel R&D India Pvt. Ltd., Chennai. I'm currently working in C# and C++, but I've done some Java programming as well. I was a Microsoft MVP in Visual C# from 2007 to 2009.
 
You can read My Blog here. I've also done some open source software - please visit my website to know more.

Comments and Discussions

 
GeneralCute Pinmembersupercat91-Sep-09 12:59 
GeneralRe: Cute PinmemberS. Senthil Kumar1-Sep-09 19:23 
GeneralRe: Cute Pinmembersupercat92-Sep-09 5:04 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140827.1 | Last Updated 1 Sep 2009
Article Copyright 2009 by S. Senthil Kumar
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid