A lambda anonymous methods, that allows you to declare your method code inline instead of with a delegate function.
All lambda expressions use the lambda operator =>, which is read as "goes to". The left side of the lambda operator specifies the input parameters (if any) and the right side holds the expression or statement block. The lambda expression x => x * x is read "x goes to x times x."
(int x) => x + 1 // explicitly typed parameter
(y,z) => return y * z; // implicitly typed parameter
Note:
1. Lambdas are not allowed on the left side of the is or as operator.
To show lambda expressions in context, consider the problem where you have an array with 10 digits in it, and you want to filter for all digits greater than 5. In this case, you can use the Where extension method, passing a lambda expression as an argument to the Where method:
int[] source = new[] { 3, 8, 4, 6, 1, 7, 9, 2, 4, 8 };
foreach (int i in source.Where(x => x > 5))
Console.WriteLine(i);
First, a quick review of delegates:
Defining, Creating, and Using a Delegate
In C#, a delegate is a data structure that refers to either a static method, or an object and an instance method of its class. When you initialize a delegate, you initialize it with either a static method, or a class instance and an instance method.
The following code shows the definition of a delegate and a method that can be used to initialize the delegate:
// Defines a delegate that takes an int and returns an int
public delegate int ChangeInt(int x);
// Define a method to which the delegate can point
static public int DoubleIt(int x)
{
return x * 2;
}
Now, you can create and initialize an instance of the delegate, and then call it:
ChangeInt myDelegate = new ChangeInt(DelegateSample.DoubleIt);
Console.WriteLine("{0}", myDelegate(5));
This, as you would expect, writes 10 to the console.
Using an Anonymous Method
With C# 2.0, anonymous methods allow you to write a method and initialize a delegate in place:
ChangeInt myDelegate = new ChangeInt(
delegate(int x)
{
return x * 2;
}
);
Console.WriteLine("{0}", myDelegate(5));
Using a Lambda Expression
With Lambda expressions, the syntax gets even terser:
ChangeInt myDelegate = x => x * 2;
Console.WriteLine("{0}", myDelegate(5));
This lambda expression is an anonymous method that takes one argument x, and returns x * 2. In this case, the type of x and the type that the lambda returns are inferred from the type of the delegate to which the lambda is assigned.
If you wanted to, you could have specified the type of the argument, as follows:
ChangeInt myDelegate = (int x) => x * 2;
Console.WriteLine("{0}", myDelegate(5));
Using a Lambda with Two Arguments
When using the Standard Query Operators, on occasion, you need to write a lambda expression that takes two arguments.
If you have a delegate that takes two arguments:
// Defines a delegate that takes two ints and returns an int
public delegate int MultiplyInts(int arg, int arg2);
You can declare and initialize a delegate:
MultiplyInts myDelegate = (a, b) => a * b;
Console.WriteLine("{0}", myDelegate(5, 2));
Statement Lambda Expressions
You can write a more complicated lambda expression using statements, enclosing the statements in braces. If you use this syntax, you must use the return statement, unless the lambda returns void:
int[] source = new[] { 3, 8, 4, 6, 1, 7, 9, 2, 4, 8 };
foreach (int i in source.Where(
x =>
{
if (x <= 3)
return true;
else if (x >= 7)
return true;
return false;
}
))
Console.WriteLine(i);
Sometimes developers wonder how to pronounce the => token.
If the lambda expression is a predicate, expressing some condition: c => c.State == "WA" then the => can be spoken as "such that". In this example, you could say "c such that c dot state equals Washington". If the lambda expression is a projection, returning a new type: c => new XElement("CustomerID", c.CustomerID); then the => can be spoken as "becomes". In the above example, you could say "c becomes new XElement with a name of CustomerID and its value is c dot CustomerID". Or "maps to", or "evaluate to", as suggested in the comments below. But most often, I just say "arrow". J
A quick note: predicates are simply boolean expressions that are passed to some method that will use the boolean expression to filter something. A lambda expression used for projection takes one type, and returns a different type. More on both of these concepts later.
The Func Delegate Types
The framework defines a number of parameterized delegate types:
public delegate TR Func
public delegate TR Func
public delegate TR Func
public delegate TR Func
public delegate TR Func
In the above delegate types, notice that if there is only one type parameter, it is the return type of the delegate. If there are two type parameters, the first type parameter is the type of the one and only argument, and the second type is the return type of the delegate, and so on. Many of the standard query operators (which are just methods that you call) take as an argument a delegate of one of these types.
Expression Trees
Lambda expressions can also be used as expression trees. This is an interesting topic, but is not part of this discussion on writing pure functional transformations.
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment