|Deep C# - Anonymous Methods, Lambdas And Closures|
|Monday, 19 September 2016|
Page 2 of 5
The idea of an anonymous method allows you to fuse the identity of the delegate with the function it wraps.
The syntax is easy, you simply use the delegate keyword to stand in for the name of the function you are trying to wrap and follow it by a definition of that function. Notice that this means that you don't have to create a separate method that has a life of its own that you then wrap in the delegate - this also saves having to give the method a name.
For example, we can create an instance of MyHelloDelegateType:
One identifier fewer might not seem much of a victory but now we can recast the code to express the fact that the delegate type is really about the signature and the delegate instance is about what actually happens by renaming the delegate “Hello” i.e. the name that we probably would have assigned the method:
You can specify parameters in the function definition by treating the keyword “delegate” as if it was the function’s name. For example:
However for this to work we need to define another delegate type that matches the new signature:
Notice that the identifier used as the parameter in the type definition doesn’t carry any meaning – it’s just there for the syntax.
Perhaps the C style signature specification:
would be better but notice, this doesn’t work in C# .
With the type defined we can now call the delegate in the usual way:
The situation is a little more complicated than this simple example suggests.
In fact the anonymous method doesn’t have to match the signature of the delegate type exactly.
As long as the delegate type has no out parameters then the anonymous method can be defined with no parameters.
For example the following is perfectly legal even though the delegate type specifies a single string parameter:
However you still have to call the delegate with the correct signature:
The parameter supplied is simply thrown away. You can see why this approach doesn’t work without parameters. If there is an out parameter defined, where would the return value come from?
Using anonymous methods
So what are anonymous methods good for?
They certainly save one level of naming confusion but in some cases they can remove the need for any new names at all.
For example, consider the Find method of the Array object defined as:
The Predicate delegate is defined as:
Without anonymous methods you would have to define a Predicate method, wrap in a delegate and pass it to the Find method.
With anonymous method it can be as simple as:
In short, anonymous methods are good for short functions that you want to use “at once”, often as a parameter within a method call.
However in modern C# lambdas provide a simpler way of doing the same job and more. They work in the same way as anonymous methods but provide a neater way of writing the code.
Lambdas sound esoteric; the name comes from lambda calculus which is important in computer science. You don't need to worry about theory because lambdas solve a very practical problem.
There are two slight variations on the basic idea of a lambda - statement and expression lambdas. It makes sense to start off looking at statement lambdas because these are simply a more concise way of writing an anonymous method.
The basic syntax is:
The => symbol can be read as “becomes” to indicate that the parameters are transformed into the actions.
A lambda expression shares all its characteristics with anonymous methods.
For example, to define the Hello anonymous method listed earlier using a lambda expression you would write something like:
The idea is that you are still creating an anonymous method but the body of the method is now defined using a slightly different syntax. Once the lambda expression is encapsulated by the delegate instance everything works in the same way. Note there is nothing special about the name param1 - you can call parameters whatever you want.
There are some tricks that you can use with lambda expressions to make the method definition even more concise and flexible.
The first is that the compiler can deduce the type of the parameters from the delegate type.
Essentially the lambda expression has to have the same number of parameters as the delegate and the return type, if any, has to be implicitly convertible to the return type of the delegate.
Thus the previous lambda expression can be written:
You can also leave out the brackets if the lambda has only one parameter
and you can use empty brackets () if there are no parameters at all.
You can use a lambda anywhere you would use an anonymous method and they are most often used as parameters as an easy way to pass a function to a method.
|Last Updated ( Thursday, 22 September 2016 )|