Expression LambdasUnlike a statement lambda, which includes a statement block and, therefore, zero or more statements, an expression lambda has only an expression, with no statement block. Listing 12.18 is the same as Listing 12.14, except that it uses an expression lambda rather than a statement lambda. Listing 12.18: Passing a Delegate with a Statement Lambda class DelegateSample { // ... static void Main(string[] args) { int i; int[] items = new int[5]; for (i = 0; i < items.Length; i++) { Console.Write("Enter an integer:"); items[i] = int.Parse(Console.ReadLine()); }
for (i = 0; i < items.Length; i++) { Console.WriteLine(items[i]); } } }The difference between a statement and an expression lambda is that the statement lambda has a statement block on the right side of the lambda operator, whereas the expression lambda has only an expression (no return statement or curly braces, for example).Generally, you would read a lambda operator in an expression lambda in the same way you would a statement lambda: "go/goes to." In addition, "becomes" is sometimes clearer. In cases such as the BubbleSort() call, where the expression lambda specified is a predicate (returns a Boolean), it is frequently clearer to replace the lambda operator with "such that." This changes the pronunciation of the statement lambda in Listing 12.18 to read "first and second such that first is less than second." One of the most common places for a predicate to appear is in the call to System.Linq.Enumerable()' s Where() function. In cases such as this, neither "such that" nor "goes to" is needed. We would read names.Where(name => name.Contains(" ")) as "names where names dot Contains a space," for example.One pronunciation difference between the lambda operator in statement lambdas and in expression lambdas is that "such that" terminology applies more to expression lambdas than to statements lambda since the latter tend to be more complex.The anonymous function does not have any intrinsic type associated with it, although implicit conversion is possible for any delegate type as long as the parameters and return type are compatible. In other words, an anonymous method is no more a ComparisonHandler type than another delegate type such as LessThanHandler. As a result, you cannot use the typeof() operator (see Chapter 17) on an anonymous method, and calling GetType() is possible only after assigning or casting the anonymous method to a delegate variable.Table 12.1 contains additional lambda expression characteristics.TABLE 12.1: Lambda Expression Notes and Examples
// ERROR: Operator '.' cannot be applied to// operand of type'lambda expression'Type type = ((intx) => x).ToString(); ;
// ERROR: The first operand of an 'is' or 'as'// operator may not be a lambda expression or// anonymous methodbool boolean = ((int x) => x) is Func<int, int>; }
// ERROR: Lambda expression is not compatible with// Func<int, bool> type.Func<int, bool> expression = ((int x) => x);
// ERROR: Cannot assign lambda expression to an// implicitly typed local variablevar thing = (x => x);
// ERROR: Control cannot leave the body of an// anonymous method or lambdaexpressionstring[] args;Func<string> expression;switch(args[0]){case "/File":expression = () =>{if (!File.Exists(args[1])){break;}// ...return args[1];};// ...}
// ERROR: The name 'first' does not// exist in the current contextFunc<int, int, bool> expression =(first, second) => first > second;first++; }
int number;Func<string, bool> expression =text => int.TryParse(text, out number);if (expression("1")){// ERROR: Use of unassigned local variableSystem.Console.Write(number);}int number;Func<int, bool> isFortyTwo =x => 42 == (number = x);if (isFortyTwo(42)){// ERROR: Use of unassignedlocal variableSystem.Console.Write(number);}