Lambda syntax in C# 3 makes it really convenient to create one-liner anonymous methods. They're a definite improvement over the wordier anonymous delegate syntax that C# 2 gave us. The convenience of lambdas, however, brings with it a temptation to use them in places where we don't necessarily need the functional programming semantics they provide.
For instance, I frequently find that my event handlers are (or at least start out as) simple one-liners that set a state value, or call another function, or set a property on another object, etc. For these, should I clutter my class with yet another simple function, or should I just stuff a lambda into the event in my constructor?
There are some obvious disadvantages to lambdas in this scenario:
These two things don't bother me much, for the reasons stated. And I could solve both of those problems, if they really were problems, by storing the lambda in a member delegate, but that would kind of defeat the purposes of using lambdas for their convenience and of keeping the class clean of clutter.
There are two other things, though, that I think are maybe not so obvious, but possibly more problematic.
Each lambda function forms a closure over its containing scope. This could mean that temporary objects created earlier in the constructor stay alive for much longer than they need to due to the closures maintaining references to them. Now hopefully, the compiler is smart enough to exclude objects from the closure that the lambda doesn't use, but I'm not sure. Does anybody know?
Luckily again, this isn't always an issue, as I don't often create temporary objects in my constructors. I can imagine a scenario where I did, though, and where I couldn't easily scope it outside of the lambda.
So I want to draw on the advice and experience of others, perhaps those with experience in other languages with functional programming features. Are there any established best practices for this kind of thing? Would you avoid using lambdas in event handlers or in other cases where the lambda significantly outlives its enclosing scope? If not, at what threshold would you decide to use a real function instead of a lambda? Have any of the above pitfalls significantly bitten anybody? Are there any pitfalls I haven't thought of?
The number 3000 is AWS Lambda's burst concurrency limit in us-east-1 region. After the initial burst, your functions' concurrency can scale by an additional 500 instances each minute. This continues until there are enough instances to serve all requests, or until a concurrency limit is reached.
Best practices suggest that one separate the handler from the Lambda's core logic. Not only is it okay to add additional definitions, it can lead to more legible code and reduce waste--e.g. multiple API calls to S3.
Use a Lambda when you need to access several services or do custom processing. As data flows through services, you use Lambdas to run custom code on that data stream. This is useful in a Kinesis Pipeline that's receiving data from things like IoT devices.
I generally have one routine dedicated to wiring up event handlers. Therein, i use anonymous delegates or lambdas for the actual handlers, keeping them as short as possible. These handlers have two tasks:
This done, i've avoided cluttering up my class namespace with event handler methods that cannot be cleanly used for other purposes, and forced myself to think about the needs and purposes of the action methods that i do implement, generally resulting in cleaner code.
Each lambda function forms a closure over its containing scope. This could mean that temporary objects created earlier in the constructor stay alive for much longer than they need to due to the closures maintaining references to them. Now hopefully, the compiler is smart enough to exclude objects from the closure that the lambda doesn't use, but I'm not sure. Does anybody know?
From what I have read, the C# compiler either generates an anonymous method, or an anonymous inner class, depending on if it needs to close over the containing scope or not.
In other words, if you don't access the containing scope from within your lambda, it won't generate up the closure.
However, this is a bit of "hearsay", and I'd love to have someone who is more knowledgeable with the C# compiler weigh in on that.
All that said, the old C# 2.0 anonymous delegate syntax did the same thing, and I've almost always uses anonymous delegates for short event handlers.
You have covered the various pros and cons quite well, if you need to unhook your event handler, don't use an anonymous method, otherwise I'm all for it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With