127

I currently have a page which is declared as follows:

public partial class MyPage : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        //snip
        MyButton.Click += (o, i) =>
        {
            //snip
        }
    }
}

I've only recently moved to .NET 3.5 from 1.1, so I'm used to writing event handlers outside of the Page_Load. My question is; are there any performance drawbacks or pitfalls I should watch out for when using the lambda method for this? I prefer it, as it's certainly more concise, but I do not want to sacrifice performance to use it. Thanks.

CJBS
  • 15,147
  • 6
  • 86
  • 135
Christopher Garcia
  • 2,536
  • 7
  • 30
  • 40

4 Answers4

132

There are no performance implications since the compiler will translate your lambda expression into an equivalent delegate. Lambda expressions are nothing more than a language feature that the compiler translates into the exact same code that you are used to working with.

The compiler will convert the code you have to something like this:

public partial class MyPage : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        //snip
        MyButton.Click += new EventHandler(delegate (Object o, EventArgs a) 
        {
            //snip
        });
    }
}
Code Maverick
  • 20,171
  • 12
  • 62
  • 114
Andrew Hare
  • 344,730
  • 71
  • 640
  • 635
  • I see. So is there also no drawback from having these handlers inside of Page_Load versus having them outside of it? – Christopher Garcia Mar 17 '10 at 20:15
  • 1
    The prevailing convention is to attach event handlers in the `OnInit` method but since a button's `Click` event will be raised after the page loads this example is fine. – Andrew Hare Mar 17 '10 at 20:51
  • 11
    Important to note that without retaining a reference to the delegate, you can't unsubscribe from the event. – snarf Nov 15 '13 at 18:03
  • 3
    "the exact same code" is a bit misleading; at least when referencing local variables from the enclosing method, the lambda expressions are not translated into methods *and* something like a closure object that stores the current values of the local variables. – O. R. Mapper Dec 18 '13 at 19:37
78

Performance-wise it's the same as a named method. The big problem is when you do the following:

MyButton.Click -= (o, i) => 
{ 
    //snip 
} 

It will probably try to remove a different lambda, leaving the original one there. So the lesson is that it's fine unless you also want to be able to remove the handler.

Code Maverick
  • 20,171
  • 12
  • 62
  • 114
Gabe
  • 84,912
  • 12
  • 139
  • 238
  • 3
    "It will *probably* try to ..."? Will it *ever* remove the correct handler in such a situation? – O. R. Mapper Dec 18 '13 at 19:38
  • 1
    @O.R.Mapper: If the lambda captures a variable, it can't remove the correct handler. In other circumstances, it's up to the compiler. – Gabe Dec 18 '13 at 22:29
  • Really? Interesting - so, if I register two anonymous functions that look the same (w.l.o.g. have an empty body), and then I unregister (using `-=`) another anonymous function that too has an empty body, it is essentially undefined which of the two event handlers will be removed, or whether any of them will be removed at all? – O. R. Mapper Dec 19 '13 at 08:43
  • 4
    @O.R.Mapper: Yes. The compiler is allowed to (but does not have to) make equal delegates if they have identical semantics (the code doesn't have to be the same, but they must do the same thing) and capture the same variable instances (not just the same variables, but the same instances of those variables). See section 7.10.8 (Delegate equality operators) of the C# spec for all the details. – Gabe Dec 19 '13 at 13:44
  • 15
    If you really want to use the lambda but need to remove the event, you can always keep hold of the object in a local variable / field then remove that, e.g. `var event = (o, e) => doSomething(); handler += event; doSomethingElse(); handler -= event;` – Wai Ha Lee Mar 01 '14 at 10:49
  • This was driving me nuts when trying to debug why my events were not unsubscribing but it all makes sense now! For example if you have a Winforms button (checkbox, textbox, whatever..) and add a watch to the controls Events InvokationList you will see that when using lambda functions, you will have the exact behavior described above! I took @WaiHaLee 's advice and moved it to a local variable: public event EventHasndler myEvent += new EventHandler((sender, e) => mymethod); then subscribed to that. – Hooplator15 Jul 25 '19 at 16:32
49
EventHandler handler = (s, e) => MessageBox.Show("Woho");

button.Click += handler;
button.Click -= handler;
Code Maverick
  • 20,171
  • 12
  • 62
  • 114
3

No performance implications that I'm aware of or have ever run into, as far as I know its just "syntactic sugar" and compiles down to the same thing as using delegate syntax, etc.

heisenberg
  • 9,665
  • 1
  • 30
  • 38