Lambda expressions are a powerful way to make code more dynamic, easier to extend and also faster. They can be also used to reduce potential errors and make use of static typing and intelligence as well as the superior IDE of Visual Studio.
In the first version of C#, the construct of delegates has been introduced. This concept has been integrated to make passing functions possible. In a sense, a delegate is a strongly typed function pointer. A delegate can be much more, but in essence, that is what you get out. The problem was that passing a function required quite a lot of steps (usually):
- Writing the delegate (like a class), which includes specifying the return and argument types.
- Using the delegate as the type in the method that should receive some function with the signature that is described by the delegate.
- Creating an instance of the delegate with the specific function to be passed by this delegate type.
So let's improve this syntax and extend the possibilities. First of all where does this name come from? The name is actually derived from the lambda calculus in mathematics, which basically just states what is really required to express a function. More precisely it is a formal system in mathematical logic for expressing computation by way of variable binding and substitution. So basically we have between 0 and N input arguments and one return value. In our programming language we can also have no return value (void).
Let's have a look at some example lambda expressions:
C# 3.0 has added lambda expression. Lambda expressions are an even more compact syntax for defining anonymous functions (anonymous methods and lambda expressions are collectively referred to as anonymous functions). The following section of code filters a list of cities as we did before, but this time using a lambda expression.
string[] cities = { "Boston", "Los Angeles",
"Seattle", "London", "Hyderabad" };
IEnumerable<string> filteredList =
cities.Where(s => s.StartsWith("L"));
The distinguishing feature in this code is the "goes to" operator (=>). The left hand side of the => operator defines the function signature, while the right hand side of the => operator defines the function body.
You'll notice that the lambda expression doesn't require a delegate keyword. The C# compiler automatically converts lambda expressions into a compatible delegate type or an expression tree. You'll also notice the function signature doesn't include any type information for the parameter named s. We are using an implicitly typed signature and letting the C# compiler figure out the type of the parameter based on the context. In this case, the C# compiler can deduce that s is of type string. We could also choose to type our parameter explicitly.
IEnumerable<string> filteredList =
cities.Where((string s) => s.StartsWith("L"));
Parentheses are required around the function signature when we use explicit typing, or when there is zero or more than one parameter. In other words, the parentheses are optional when we are using a single, implicitly typed parameter. An empty set of parentheses is required when there are no parameters for the expression.
The right hand side of a lambda may contain an expression or a statement block inside { and } delimiters. Our city filter above uses an expression. Here is the same filter using a statement block.
IEnumerable<string> filteredList =
cities.Where(s => { string temp = s.ToLower();
return temp.StartsWith("L");
});
Notice the statement block form allows us to use multiple statements and provide local variable declarations. We also need to include a return statement. Statement blocks are useful in more complex lambda expressions, but the general guideline is to keep lambda expressions short.
No comments:
Post a Comment