2

I have a button event declared like this :

myButton.Click += new EventHandler(ButtonClicked);

private void ButtonClicked(Object s, EventArgs e)
{
  this.Close();
}

I can do exactly the same like this :

myButton.Click += (s, e) => this.Close();

I'm sure the advantage of using the second way of doing it is not just aesthetic.

Why and when should I use the second method because now I'm confused? If it's just for the look of it, it doesn't look much cleaner when you have more than one instructions in the body of your anonymous function.

Servy
  • 202,030
  • 26
  • 332
  • 449
phadaphunk
  • 12,785
  • 15
  • 73
  • 107
  • This is a scenario for example, when creating worker-threads that do not require a large method body, or a reusable method, which you want to use somewhere else in you class. It's just a little faster to type and inline (consider also LINQ). Look [here](http://msdn.microsoft.com/en-us/library/bb397687.aspx). – bash.d Feb 20 '13 at 14:02
  • Related: http://stackoverflow.com/questions/73227/what-is-the-difference-between-lambdas-and-delegates-in-the-net-framework – Frédéric Hamidi Feb 20 '13 at 14:03

8 Answers8

4

Technically there is no difference. Compiler will generate handler method in second case.

But frankly speaking I almost never use anonymous event handlers. Why? because they do not have names. IDE can't help me to find place where event is handled. Do you remember exact place where you subscribed with anonymous method? Well, you possibly remember that place. But I bet your teammates don't.

Also I don't like mixing styles of event handlers. Visual Studio generates for me button1_Click methods. I don't like having some handlers subscribed this way, and some subscribed in place.

And I like to see event argument type. And yes unsubscribing also matters sometime. And few more points - anonymous methods are useful for very simple logic (like closing form in your case), but them become very messy with something more complex. And I think that putting event handler in place breaks single responsibility of your method. It subscribes to event, does some other stuff, and handles event in same place. I like to separate things in order to make them more readable and maintainable.

Sergey Berezovskiy
  • 232,247
  • 41
  • 429
  • 459
  • 1
    I like your answer ! It's 100% true it can be confusing to teammates working on your code. The best way around this I think is a general place where they should all be and a good way of naming your controls. (In the case of event handling) – phadaphunk Feb 20 '13 at 14:19
  • 1
    @PhaDaPhunk I usually create region named *Event Handlers* where I put all event handlers. That makes finding them very easy to all of team members. Well, if I have many event handlers (and that usually true for complex forms) – Sergey Berezovskiy Feb 20 '13 at 14:21
2

The compiler generates a method for this anonymous function (s, e) => this.Close(); either way,

It's up to you where you want to use it, declaring it inside a method will however let you access variables declared in that method.

animaonline
  • 3,715
  • 5
  • 30
  • 57
1

Well you have essentially implictly applied a delegate to your Click event.

You can't access this event in code anywhere else. The main advantage to this is that you can't call your method any where else in your class, by having a method you are inviting other "Team Members" to access the method in their code or potentially change the modifiers of it to what they think should happen.

Should you want to be able to override a method, then obviously inline anonymous assignments are a dis-advantage.

The usage is more or less dependant on how you want to handle access to the logic.

LukeHennerley
  • 6,344
  • 1
  • 32
  • 50
  • Ok so I guess the rule of thumb here is if I'm sure my method is applicable to this event and this event only, I should use the short way. But in a case where I need something I would re-use I can't. I knew that I wouldn't be able to re-use it but with all these answers I realize that there is not any performance benefit when using the lambda. Thanks ! – phadaphunk Feb 20 '13 at 14:08
  • @PhaDaPhunk in a sense, yes that's right. You also have to consider if you are doing inheritance of some sort, you need your `Click` event to be accessed. You then need to ignore delegate's and use a normal method with the `virtual` keyword, even though it is potentially exclusive to one area :) – LukeHennerley Feb 20 '13 at 14:11
  • Oooh right. So I guess using using it requires more thinking than I thought because it can trap you afterwards. – phadaphunk Feb 20 '13 at 14:13
1

You can do it even more elegant if you do not need the arguments:

myButton.Click += delegate { this.Close(); };

but there is no profit besides elegant look behind it.

I prefer NOT to use lambda expressions ( => ) if I don't really need them as you can't change the scope code during debugging.

VladL
  • 12,769
  • 10
  • 63
  • 83
  • Oh nice didn't know about this ! This delegate / lambda concept is just sooo overwhelming to me right now... thank ! – phadaphunk Feb 20 '13 at 14:09
  • @PhaDaPhunk you are welcome. If you are c# newbie, so VS debugger is your friend. And lambdas are not debugger friendly :) – VladL Feb 20 '13 at 14:15
1

Anonymous Functions can be anonymous methods or lambda expressions. The lamba expression is of the form:

() => //dowork

Anonymous Methods are more verbose and support remains mainly for backwards compatibility. Anonymous Functions do not have a value or type in and of themselves, but it is convertible to a delegate or expression tree. Anonymous functions allow us to create in-line methods which are useful in cases such as setting up an event handler. This in-lining of methods allows developers to write code "in the same place". In other words, the handler is immediately available to the reader at the location where the event is handled.

I strive to in-line methods when the implementation is limited to a few statements and not re-useable (as is often the case in event handlers). Lamba Expressions can also used extensively in the framework's extensions methods Enumerable.Select, Where etc. And in place of Action or Func when using the new parallels library or calling Control.Invoke.

P.Brian.Mackey
  • 43,228
  • 68
  • 238
  • 348
0

The first method is easier to support, to make more complex and to reuse.

Also it is not obvious how to unsubscribe the second method from the event

Dmitrii Dovgopolyi
  • 6,231
  • 2
  • 27
  • 44
0

Here is a similiar subject: delegate keyword vs. lambda notation that considers anonymous delegates and lambda expressions. Particurarly, the answer there is: Once it is compiled, there is no difference between them.

Community
  • 1
  • 1
Ryszard Dżegan
  • 24,366
  • 6
  • 38
  • 56
0

As long as you don't need the parameters, you can even use:

myButton.Click += delegate { this.Close(); };

which looks even cleaner.

But by using anonymous delegates comes the cost of code reusability, as others have pointed out. Also in the article How to: Subscribe to and Unsubscribe from Events. Microsoft states that:

It is important to notice that you cannot easily unsubscribe from an event if you used an anonymous function to subscribe to it. To unsubscribe in this scenario, it is necessary to go back to the code where you subscribe to the event, store the anonymous method in a delegate variable, and then add the delegate to the event. In general, we recommend that you do not use anonymous functions to subscribe to events if you will have to unsubscribe from the event at some later point in your code.

One of the strong points of the anonymous methods, which also separates them from lambda expressions, is that:

... There is one case in which an anonymous method provides functionality not found in lambda expressions. Anonymous methods enable you to omit the parameter list. This means that an anonymous method can be converted to delegates with a variety of signatures. This is not possible with lambda expressions.

As a conclusion for the paragraph above we can say that you can either pass no parameters at all, or you should pass in the exact signature of the event handler:

myButton.Click += delegate(object sender, EventArgs e) { this.Close(); };
Alex Filipovici
  • 31,789
  • 6
  • 54
  • 78