Thursday, January 17, 2008

Predicate: Logic. that which is affirmed or denied concerning the subject of a proposition.

In programming terms, a function that returns true or false taking a subject as a parameter. So, Predicate<T> is really just a specific signature applied to a delegate. A method compliant with this signature looks like:

bool method(T item)

The collection classes in System.Collections.Generic have several methods that will take a predicate as a parameter. I really like this separation of concerns. The responsibility of iterating through the collection is owned by the collection; the responsibility of making a decision based on data in an object is owned by the object. What seemed to be missing to me was the common operation of combining boolean results with logical operators. What I really wanted to do was to pass a set of predicate functions to the collection methods. Of course, the collection authors could not know how I would want the boolean results combined. This seemed to be the responsibility of something else that could contain a list of predicates, but at the same time return a predicate function that is the logical combination of the results.

The PredicateList class is a container of Predicate<T> delegates. The methods that can be used as a predicate are the logical AND and OR operations. These methods iterate through the contained predicates and short circuit when arriving at a value that determines the result of the operation.

using System;
using System.Collections.Generic;

namespace Utilities
{
  public class PredicateList<T> : List<Predicate<T>>
  {
    public PredicateList(params Predicate<T>[] predicates)
    {  AddRange(predicates);  }
    public bool And(T item)
    {
      foreach (Predicate<T> pred in this)
      {
        if (!pred(item)) return false;
      }
      return true;
    }
    public bool Or(T item)
    {
      foreach (Predicate<T> pred in this)
      {
        if (pred(item)) return true;
      }
      return false;
    }
  }
}

Using this class with one of the collection methods would look like:

PredicateList<T> filters = new PredicateList<T>(IsThis, IsThat, IsTheOtherThing);
return FindAll(filters.And);

Thursday, January 17, 2008 10:31:02 AM (Eastern Standard Time, UTC-05:00)  #    Comments [1]  |  Trackback
Sunday, January 20, 2008 3:59:11 PM (Eastern Standard Time, UTC-05:00)
Nice post... and very concise code that combines some .NET best practices with an understanding of the framework. E.g. generics, delegation, variable argument lists.
Comments are closed.

Theme design by Jelle Druyts