BlackWaspTM

This web site uses cookies. By using the site you accept the cookie policy.This message is for compliance with the UK ICO law.

.NET Framework
.NET 2.0+

The Generic Predicate Delegate

The generic Predicate delegate represents a method or function that accepts an object of any type and returns a Boolean result. It is often used to define a set of criteria for filtering collections such as arrays and generic lists.

What is a Predicate?

A predicate is a logical expression that yields a result of either true or false. Predicates are often used in conditional processing, particularly with "if" statements. For example, in the following C# code the predicate is "value > 10". If the value variable is larger than ten the expression returns true. If it is ten or less, the predicate evaluates as false.

if (value > 10) Console.WriteLine("Large");

The Predicate<T> Delegate

The Predicate<T> delegate is a pre-defined delegate that was introduced in the .NET framework 2.0. It is a generic delegate that is used to reference a method that accepts a parameter of any type and returns a Boolean result. The delegate is used by some of the classes provided by the .NET framework. For example, you can search the contents of arrays and generic lists for items that meet given criteria. The criteria are provided to the appropriate methods using a Predicate<T> parameter.

To demonstrate, add the following code to a console application and execute it in the debugger to see the results. This example creates an integer array containing nine prime numbers. It uses the FindAll method to generate another array containing the prime numbers between zero and nine. The condition is defined in a method that is passed to the second, Predicate<T> argument.

static void Main()
{
    int[] primes = new int[] { 2, 3, 5, 7, 11, 13, 17, 19, 21 };
    int[] smallPrimes = Array.FindAll(primes, IsSingleDigit);   // { 2, 3, 5, 7 }
}

static bool IsSingleDigit(int value)
{
    return 0 <= value && value <= 9;
}

We can simplify the code using an anonymous method for the predicate parameter, as long as it has a single argument and returns a Boolean. The code below is functionally identical to the previous sample.

int[] primes = new int[] { 2, 3, 5, 7, 11, 13, 17, 19, 21 };
int[] smallPrimes = Array.FindAll(primes,
    delegate(int value) { return 0 <= value && value <= 9; });  // { 2, 3, 5, 7 }

NB: When using the .NET framework version 3.5 or later, the functionality provided by the Predicate delegate can be replicated using Language Integrated-Query (LINQ).

Creating a Predicate<T> Parameter

You can create your own methods with Predicate<T> arguments, allowing you to accept a condition to check within the method body. To demonstrate, let's create a method that allows an ArrayList to be searched in a similar manner to the array search described above. We will create a method that receives an ArrayList and a predicate and returns a new ArrayList containing a filtered set of values.

The method is shown below. First a new ArrayList object is created. Next we loop through all of the items in the passed list, running predicate for each. If the result of the operation is true, the item is added to the filtered list. When the loop completes, the list of items that matched the criteria is returned.

static ArrayList FindAll<T>(ArrayList items, Predicate<T> criteria)
{
    ArrayList matches = new ArrayList();
    foreach (T item in items)
    {
        if (criteria(item)) matches.Add(item);
    }
    return matches;
}

We can test the method by calling it using several predicates. The code below finds the numbers from an ArrayList that are between zero and nine and all of the numbers that are palindromes.

static void Main()
{
    ArrayList primes = new ArrayList(new int[] { 2, 3, 5, 7, 11, 13, 17, 19, 21 });
    ArrayList small = FindAll<int>(primes, IsSingleDigit);    // { 2, 3, 5, 7 }
    ArrayList palin = FindAll<int>(primes, IsPalindrome);     // { 2, 3, 5, 7, 11 }
}

static bool IsSingleDigit(int value)
{
    return 0 <= value && value <= 9;
}

static bool IsPalindrome(int value)
{
    string forwards = value.ToString();
    char[] chars = forwards.ToCharArray();
    Array.Reverse(chars);
    string backwards = new string(chars);
    return forwards == backwards;
}
20 February 2011