RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


From Delegate to Lambda : Page 2

The key to understanding lambda expressions lies in understanding delegates.

Filtering with Delegates
Your goal now is to replace the GetEvenNumbers method in Listing 1 and Listing 2 with a more generic method called Select(). You can use a delegate as a parameter type. So declare a delegate named "Filter" for this purpose:

   // In C#:
   delegate bool Filter( int x );
   ' in VB:
   Delegate Function Filter(ByVal x As Integer) _
      As Boolean
The delegate takes an integer as a parameter and returns a Boolean value. The Boolean result allows you to implement filtering methods where the "x" will be included in the result if the return value of the filtering method is true.

You can now implement the Select() method, which takes a parameter of type Filter:

   // In C#:
   static List<int> Select( List<int> numbers, 
      Filter filter )
      List<int> result = new List<int>();
      foreach ( int i in numbers )
         // call delegate
         if ( filter( i ) == true )
            result.Add( i );
      return result;
   ' in VB:
   Function [Select](ByVal numbers As _
      List(Of Integer), _
      ByVal filter As Filter) _
      As List(Of Integer)
      Dim result As New List(Of Integer)
      For Each number In numbers
         ' call delegate
         If filter(number) = True Then
         End If
      Return result
   End Function
The snippets show that the Select method is able to perform a select operation without knowing what the selection criteria are. You've succeeded in making your Select method generic and reusable in many scenarios.

It's worth noting that working with delegates in C# 3.0 and VB9 has been simplified. The snippets show that you can use the filter variable as if it were an actual method. Previously you had to call the Invoke(…) method on the delegate, in this case filter.Invoke(i), in order to invoke the delegate.

Now that your reusable Select method is in place, you can write methods that match the delegate and use them to filter your collection of integers:

   // In C#:
   static bool IsEvenNumber( int x )
      return ( x % 2 == 0 );
   static bool IsOddNumber( int x )
      return ( x % 2 != 0 );
   List<int> even = Select( _numbers, IsEvenNumber );
   List<int> odd = Select( _numbers, IsOddNumber );
   Print( even );
   Print( odd );
   ' in VB:
   Function IsEvenNumber(ByVal x As Integer) _
      As Boolean
      Return (x Mod 2 = 0)
   End Function
   Function IsOddNumber(ByVal x As Integer) _
      As Boolean
      Return (x Mod 2 <> 0)
   End Function
   Dim even = _
       [Select](_numbers, AddressOf IsEvenNumber)
   Dim odd = _
       [Select](_numbers, AddressOf IsOddNumber)
Both the IsEvenNumber and IsOddNumber match the Filter delegate and you can therefore use them when calling the Select() method. The use of the delegate as a parameter type allows you to create a parameter that looks like it is a pointer or reference to a method; however, it is neither! The parameter is an object that inherits from System.Delegate. It is the C# compiler that does the magic of letting you pass in a method name as if it is a reference to the method. In C# 2.0, the syntax for calling Select() is different; you need to create an instance of the delegate object like so:

   List<int> even = Select( 
      _numbers, new Filter( IsEvenNumber ) );
Also notice how VB does not perform the same magic and requires you to use the AddressOf keyword.

Close Icon
Thanks for your registration, follow us on our social networks to keep up-to-date