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.




Building the Right Environment to Support AI, Machine Learning and Deep Learning

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 result.Add(number) End If Next 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) Print(even) Print(odd)

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.

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