KnowDotNet NetRefactor

Using Predicate Delegates and Lambda Expressions in C#

Lambda Shortcuts for Anonymous Methods

by Les Smith
Print this Article Discuss in Forums

It's amazing to note the progression of the features of Visual Studio, with all of the new shortcuts as the .NET frameworks have evolved.  In this article I will show the reduction in code through several releases of C# (VB.NET offers much of the same technology).


        private static void TestFeatureProgression()
        {
            
// Example 1:
            // Olden days methodolgy for finding odd numbers in an array
            // back before even Generics were available
            ArrayList al = new ArrayList(){20, 1, 3, 4, 8, 9, 44, 47 };
            
int[] intList = new int[] {20, 1, 3, 4, 8, 9, 44, 47 };
            
ArrayList oddIntegers = new ArrayList();

            
foreach (int i in intList)
            {
                
if ((i % 2) > 0)
                {
                    oddIntegers.Add(i);
                }
// if
            } // foreach

            DisplayNumbers(oddIntegers, "using an array search");

            
// or since we now have generics, we can jump ahead and
            // convert the arraylist to a generic list and pass it to
            // the method that displays a List<>
            DisplayNumbers(new List<int>(oddIntegers.ToArray(typeof(int)) as int[]),
                
"using array search printed from generic list");


            
// Now, we bring in Generics and their power.  Not only is a
            // List<int> more powerful than an ArrayList, but it is
            // strongly typed so that unlike an arraylist, you cannot add
            // a string to the List<int>.  First we will create a
            // list of integers with automatic initialization just as we
            // previously did with the creation of an array.
            // which will be used by all three examples
            List<int> list = new List<int>() { 20, 1, 3, 4, 8, 9, 44, 47 };


            
// Example 2):
            // first, a Predicate delegate is a reference that returns a bool
            // note that IsOddNumber is a separate method shown below
            Predicate<int> callBack = new Predicate<int>(IsOddNumber);

            
// now you can pass the Predicate delegate to the FindAll method of the generic List
            List<int> oddNumbers = list.FindAll(callBack);

            
// at this point all even numbers are in the list evenNumbers
            DisplayNumbers(oddNumbers, "using Predicate delegate");

            
// Example 3):
            // now shorten code by using an anonymous method
            // note that we no longer need to declare and use the IsOddNumber method
            list = list.FindAll(delegate(int i) { return (i % 2) > 0; });

            DisplayNumbers(oddNumbers,
"using anonymous method");

            
// Example 4:
            // a lambda expression can even shorten it more
            // the => (lambda) symbol means that the parameter (list) on the left side
            // of the lambda symbol is to be processed by the expression on the right side
            // of the lambda symbol.  The expression was originally a formally coded delegate
            // and in Example 2, it required a method to be the target of the Predicate.
            // In the second example we shortened the code by the use of an anonymous method
            // allowing us to do away with the Predicate and its target method (IsOddNumber).
            // In Example 4 shown below, the FindAll method of the list object will call
            // the implied anonymous method for each object in the List<int>.
            // To sum up the following line of code in english:
            // My list of paramaters "[int] i" will be processed by the expression "(i % 2) > 0"
            oddNumbers = list.FindAll(i => (i % 2) > 0);

            DisplayNumbers(oddNumbers,
"using a lambda expression");

            
// you could
        }


        
/// target for the Predicate<> delegate
        static bool IsOddNumber(int i)
        {
            
// is it an even number?
            return (i % 2) > 0;
        }

        
private static void DisplayNumbers(ArrayList oddNumbers, string s)
        {
            
Console.WriteLine("Here are your odd numbers " + s);
            
foreach (int oddNumber in oddNumbers)
            {
                
Console.Write("{0}\t", oddNumber);
            }
// foreach
            Console.WriteLine(Environment.NewLine + Environment.NewLine);
        }
// method: DisplayNumbers

        private static void DisplayNumbers(List<int> oddNumbers, string s)
        {
            
Console.WriteLine("Here are your odd numbers " + s);
            
foreach (int oddNumber in oddNumbers)
            {
                
Console.Write("{0}\t", oddNumber);
            }
// foreach
            Console.WriteLine(Environment.NewLine + Environment.NewLine);
        }

We used five different methodologies in this demo, each one taking less code, but all producing the exact same result.  The results are shown below.

Here are your odd numbers using an array search
1       3       9       47


Here are your odd numbers using array search printed from generic list
1       3       9       47


Here are your odd numbers using Predicate delegate
1       3       9       47


Here are your odd numbers using anonymous method
1       3       9       47


Here are your odd numbers using a lambda expression
1       3       9       47

Writing Add-Ins for Visual Studio .NET
Writing Add-ins for Visual Studio .NET
by Les Smith
Apress Publishing