FREE BOOK

Chapter 12 - Delegates and Lambda Expressions

Posted by Addison Wesley Free Book | LINQ October 13, 2009
C# achieves the same functionality using a delegate, which encapsulates methods as objects, enabling an indirect method call bound at runtime.

Lambda Expressions
 
Introduced in C# 3.0, lambda expressions are a more succinct syntax of anonymous functions than anonymous methods, where anonymous functions is a general term that includes both lambda expressions and anonymous methods. Lambda expressions are themselves broken into two types: statement lambdas and expression lambdas. Figure 12.2 shows the hierarchical relationship between the terms.
 
 
 
 
 Figure 12.2: Anonymous Function Terminology
 
Statement Lambdas
 
With statement lambdas, C# 3.0 provides a reduced syntax for anonymous methods, a syntax that does not include the delegate keyword and adds the lambda operator, =>. Listing 12.14 shows equivalent functionality to Listing 12.12, except that Listing 12.14 uses a statement lambda rather than an anonymous method.
 
 Listing 12.14: 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]);
             }
         }
 
    }
 
When reading code that includes a lambda operator, you would replace the lambda operator with the words "go/goes to." For example, you would read n => { return n.ToString();} as "n goes to return n dot ToString." In Listing 12.15, you would read the second BubbleSort() parameter as "integers first and second go to returning the result of first less than second."
 
As readers will observe, the syntax in Listing 12.14 is virtually identical to that in Listing 12.12, apart from the changes already outlined. However, statement lambdas allow for an additional shortcut via type parameter inference. Rather than explicitly declaring the data type of the parameters, statement lambdas can omit parameter types as long as the compiler can infer the types. In Listing 12.15, the delegate data type is bool Comparison- Handler(int first, int second), so the compiler verifies that the return type is a bool and infers that the input parameters are both integers (int).
 
 
BubbleSort(items,(int first, int second) =>
 {
 
return first < second;
 }
 );
 

 Listing 12.15: Omitting Parameter Types from Statement Lambdas
 

 // ...
 // ...
 
In general, statement lambdas do not need parameter types as long as the compiler can infer the types or can implicitly convert them to the requisite expected types. In cases where inference is not possible, the data type is required, although even when it is not required, you can specify the data type explicitly to increase readability; once the statement lambda includes one type, all types are required.
 
In general, C# requires a lambda expression to have parentheses around the parameter list regardless of whether the data type is specified. Even parameterless statement lambdas, representing delegates that have no input parameters, are coded using empty parentheses (see Listing 12.16).
 
 Listing 12.16: Parameterless Statement Lambdas
 
 
using System;
 
// ...
 
Func<string> getUserInput =
 {
 
string input;
 
do
 
{
 input = Console.ReadLine();
 }
 
while(input.Trim().Length==0);
 
return input;
 };
 
// ...
 

The exception to the parenthesis rule is that if the compiler can infer the data type and there is only a single input parameter, the statement lambda does not require parentheses (see Listing 12.17).
 
 
BubbleSort(items,
 (first, second) =>
 {
 
return first < second;
 }
 );
 
() =>
 
 Listing 12.17: Statement Lambdas with a Single Input Parameter
 

 
using System.Collections.Generic;
 
using System.Diagnostics;
 
using System.Linq;
 
// ...
 
IEnumerable<Process> processes = Process.GetProcesses().Where(
 process => { return process.WorkingSet64 > 1000000000; });
 
// ...
 

(In Listing 12.17, Where() returns a query for processes that have a physical memory utilization greater than 1GB.)
 
Note that back on Listing 12.16, the body of the statement lambda includes multiple statements inside the statement block (via curly braces). Although there can be any number of statements in a statement lambda, typically a statement lambda uses only two or three statements in its statement block. In contrast, the body of an expression lambda does not even make up a full statement since there is no statement block.

Total Pages : 9 45678

comments