12

After discovering lambda expressions, and their use as anonymous functions, I've found myself writing a lot of more trivial events such as these:

txtLogin.GotFocus += (o, e) =>
{
    txtLogin.Text = string.Empty;
    txtLogin.ForeColor = SystemColors.ControlText;
};
txtLogin.LostFocus += (o, e) =>
{
    txtLogin.Text = "Login...";
    txtLogin.ForeColor = SystemColors.InactiveCaptionText;
};

I've also moved away from event handlers which just call other functions, replacing them with small lambdas which do the same:

backgroundWorker.DoWork += (o, e) => DatabaseLookup.Open(e.Argument as string);

I've found some similar questions addressing performance concerns and pointing out that you can't remove them, but I haven't found any addressing the simple question of is this a good idea?

Is the use of lambdas in such a way considered good form, or do more experience programmers look down on this? Does it hide event handlers in hard-to-find places, or does it do the code a service by reducing the number of trivial event handlers?

Community
  • 1
  • 1
dlras2
  • 8,416
  • 7
  • 51
  • 90

3 Answers3

16

It's a perfectly reasonable idea - but in this particular case, I would use an anonymous method instead:

txtLogin.LostFocus += delegate
{
    txtLogin.Text = "Login...";
    txtLogin.ForeColor = SystemColors.InactiveCaptionText;
};

The benefit is that you don't have to specify the parameters - which makes it clearer that you're not using them. This is the only advantage that anonymous methods have over lambda expressions.

The performance hit is almost always going to be negligible. The inability to remove them afterwards is a very real problem if you do need to be able to remove the handler, but I find that often I don't. (Reactive Extensions has a nice approach to this - when you subscribe to an observable sequence, you're given back an IDisposable which will remove the subscription if you call it. Very neat.)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • what would be a good example of "you _do_ need to remove the handler"? And, what happens if the method using lambda or anonymous method is called multiple times? – Daemon Painter Aug 27 '19 at 07:40
  • 1
    @DaemonPainter: Any time you want to add a handler and then remove it later, e.g. if you want to subscribe to a button click event just during an operation, then unsubscribe. (It's the sort of situation that's easier to recognize when you're in it than it is to come up with concrete examples without having to describe a whole app.) I'm not sure what you mean by the second comment - I suspect the answer would depend on *exactly* what code you mean. It may be worth asking in a new question if you're interested. – Jon Skeet Aug 27 '19 at 07:43
1

Actually, it's consider it putting event handlers in easy-to-find places, namely right next to the name of the event it's assigned to.

A lot of the time, you'll see event handlers like:

 void Text1_KeyDown(....) {....}

attached to the KeyUp event of txtFirstName, because after using Intellisense to create the handler, someone decided to rename the textbox, and that KeyUp worked better. With the Lambda, the object, the event and the function are all together.

James Curran
  • 101,701
  • 37
  • 181
  • 258
-1

It's a tricky one. I remember reading in Code Complete about how some (smart) people say you should keep the flow of control as simple as possible, with many arguing for single entry and exit points from a method, because not doing so made the program harder to follow.

Lambdas are getting even further away from that, making it very difficult in some cases to follow what's happening, with control leaping around from place to place.

Basically, I think it probably is a bad idea because of this, but it's also powerful and makes life easier. I certainly use them a fair amount. In summary, use with caution!

Grant Crofton
  • 8,895
  • 5
  • 28
  • 38
  • 7
    Restricting yourself to a single exit point is a recipe for readability disasters, IMO. If I know the result of a method after one line (e.g. because it's a special case) then there's no reason to make the reader follow through the rest of the method to get to the exit point. – Jon Skeet Jul 14 '10 at 16:52
  • I agree, I'd always favour an early exit. But I know some people are opposed to this. – Grant Crofton Jul 15 '10 at 07:59
  • My philosophy is that it's often desirable to avoid having functions exit between the first statement that has side-effects, and the last such statement, except that returning a value from within a `try` block may be cleaner than setting a variable within the block and returning it from outside. – supercat Jun 27 '12 at 16:12