21.9 Lambda Expressions

Lambda expressions allow you to define simple, anonymous methods—that is, methods that do not have names and that are defined where they are assigned to a delegate or passed to a delegate parameter. In many cases, working with lambda expressions can reduce the size of your code and the complexity of working with delegates. As you’ll see in later examples, lambda expressions are particularly powerful when combined with the where clause in LINQ queries. Figure 21.7 reimplements the example of Fig. 21.6 using lambda expressions rather than explicitly declared methods IsEven, IsOdd and IsOver5.

Fig. 21.7 Using lambda expressions.

Alternate View

 1   // Fig. 21.7: Lambdas.cs
 2   // Using lambda expressions.
 3   using System;
 4   using System.Collections.Generic;
 5
 6   class Lambdas
 7   {
 8      // delegate for a function that receives an int and returns a bool
 9      public delegate bool NumberPredicate(int number);
10
11      static void Main(string[] args)
12      {
13         int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
14
15         // create an instance of the NumberPredicate delegate type using an
16         // implicit lambda expression
17         NumberPredicate evenPredicate = number => number % 2 == 0;
18
19         // call a lambda expression through a variable
20         Console.WriteLine(
21            $"Use a lambda-expression variable: {evenPredicate(4)}");
22
23         // filter the even numbers using a lambda expression
24         List<int> evenNumbers = FilterArray(numbers, evenPredicate);
25
26         // display the result
27         DisplayList("Use a lambda expression to filter even numbers: ",
28            evenNumbers);
29
30         // filter the odd numbers using an explicitly typed lambda
31         // expression
32         List<int> oddNumbers =
33            FilterArray(numbers, (int number) => number % 2 == 1);
34
35         // display the result
36         DisplayList("Use a lambda expression to filter odd numbers: ",
37            oddNumbers);
38
39         // filter numbers greater than 5 using an implicit lambda statement
40         List<int> numbersOver5 =
41            FilterArray(numbers, number => {return number > 5;});
42
43         // display the result
44         DisplayList("Use a lambda expression to filter numbers over 5: ",
45            numbersOver5);
46      }
47
48      // select an array's elements that satisfy the predicate
49      private static List<int> FilterArray(
50         int[] intArray, NumberPredicate predicate)
51      {
52         // hold the selected elements
53         var result = new List<int>();
54
55         // iterate over each element in the array
56         foreach (var item in intArray)
57         {
58            // if the element satisfies the predicate
59            if (predicate(item))
60            {
61               result.Add(item); // add the element to the result
62            }
63         }
64
65            return result; // return the result
66      }
67
68      // display the elements of a List
69      private static void DisplayList(string description, List<int> list)
70      {
71         Console.Write(description); // display the output's description
72
73         // iterate over each element in the List
74         foreach (int item in list)
75         {
76            Console.Write($"{item} "); // print item followed by a space
77         }
78
79         Console.WriteLine(); // add a new line
80      }
81   }

Use a lambda expression variable: True
Use a lambda expression to filter even numbers: 2 4 6 8 10
Use a lambda expression to filter odd numbers: 1 3 5 7 9
Use a lambda expression to filter numbers over 5: 6 7 8 9 10

21.9.1 Expression Lambdas

A lambda expression (line 17)


number => number % 2 == 0

begins with a parameter list (number in this case). The parameter list is followed by the => lambda operator (read as “goes to”) and an expression that represents the lambda’s body. The lambda expression in line 17 uses the % operator to determine whether the parameter’s number value is an even int. The value produced by the expression—true if the int is even, false otherwise—is implicitly returned by the lambda expression. The lambda in line 17 is called an expression lambda, because it has a single expression to the right of the lambda operator. Note that we do not specify a return type for the lambda expression— the return type is inferred from the return value or, in some cases, from a delegate’s return type. The lambda expression in line 17 is equivalent to the IsEven method in Fig. 21.6. Note that C# 6’s expression-bodied methods use a similar syntax to expression lambdas, including the lambda operator (=>).

21.9.2 Assigning Lambdas to Delegate Variables

In line 17 of Fig. 21.7, the lambda expression is assigned to a variable of type NumberPredicate—the delegate type declared in line 9. A delegate can hold a reference to a lambda expression. As with traditional methods, a method defined by a lambda expression must have a signature that’s compatible with the delegate type. The NumberPredicate delegate can hold a reference to any method that receives an int and returns a bool. Based on this, the compiler is able to infer that the lambda expression in line 17 defines a method that implicitly takes an int as an argument and returns the bool result of the expression in its body.

Lines 20–21 display the result of calling the lambda expression defined in line 17. The lambda expression is called via the variable that references it (evenPredicate). Line 24 passes evenPredicate to method FilterArray (lines 49–66), which is identical to the method used in Fig. 21.6—it uses the NumberPredicate delegate to determine whether an array element should be included in the result. Lines 27–28 display the filtered results.

21.9.3 Explicitly Typed Lambda Parameters

Lambda expressions often are used as arguments to methods with delegate-type parameters, rather than defining and referencing a separate method or defining a delegate variable that references a lambda. Lines 32–33 select the odd array elements with the lambda


(int number) => number % 2 == 1

In this case, the lambda is passed directly to method FilterArray and is implicitly stored in the NumberPredicate delegate parameter.

The lambda expression’s input parameter number is explicitly typed as an int here— sometimes this is necessary to avoid ambiguity that would lead to compilation errors (though that is not the case here). When specifying a lambda parameter’s type and/or when a lambda has more than one parameter, you must enclose the parameter list in parentheses as in line 33. The lambda expression in line 33 is equivalent to the IsOdd method defined in Fig. 21.6. Lines 36–37 of Fig. 21.7 display the filtered results.

21.9.4 Statement Lambdas

Lines 40–41 use the lambda


number => {return number > 5;}

to find the ints greater than 5 in the array and store the results. This lambda is equivalent to the IsOver5 method in Fig. 21.6.

The preceding lambda is called a statement lambda, because it contains a statement block—one or more statements enclosed in braces ({})—to the right of the lambda operator. This lambda’s signature is compatible with the NumberPredicate delegate, because the parameter number’s type is inferred to be int and the statement in the lambda returns a bool. For additional information on lambdas, visit


https://msdn.microsoft.com/library/bb397687
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset