Combining generic predicates in C#

I've got a requirement wherein I needed to have a way to make dynamic predicates, with the need to support for And and Or operations between two predicates. I was aware that there are ways to create Dynamic LINQ queries if I wanted to use LINQ to Objects (I was using these on generic lists anyway), but a voice at the back of my head told me there would be a much simpler solution.

I was astounded at how simple it turned out:

    public static class PredicateExtensions
    {
        public static Predicate<T> And<T>
            (this Predicate<T> original, Predicate<T> newPredicate)
        {
            return t => original(t) && newPredicate(t);
        }

        public static Predicate<T> Or<T>
            (this Predicate<T> original, Predicate<T> newPredicate)
        {
            return t => original(t) || newPredicate(t);
        }
    }

Of course the assumption here is that the logic operations are simple.

The following are the tests to show how it works. Needless to say, the lambda expressions can be replaced by any method following the Predicate delegate:

    [TestFixture]
    public class PredicateExtensionsTest
    {
        [Test]
        public void PredicateExtension_And_method_performs_an_and_between_orig_and_new_predicates()
        {
            int t1 = 1;

            Predicate<int> orig = t => t == 1;
            Predicate<int> newPredicate = t => (t + 1) == 2;
            Predicate<int> falsing = t => (t - 1) == -1;

            Predicate<int> origAndNew = orig.And(newPredicate);
            Predicate<int> origAndFalsing = orig.And(falsing);

            Assert.IsTrue(orig(t1));
            Assert.IsTrue(origAndNew(t1));
            Assert.IsFalse(origAndFalsing(t1));
        }

        [Test]
        public void PredicateExtension_Or_method_performs_an_or_between_orig_and_new_predicates()
        {
            int t1 = 1;

            Predicate<int> orig = t => t == 1;
            Predicate<int> newPredicate = t => (t + 1) == 2;
            Predicate<int> falsing = t => (t - 1) == -1;

            Predicate<int> origOrNew = orig.Or(newPredicate);
            Predicate<int> origOrFalsing = orig.Or(falsing);

            Assert.IsTrue(orig(t1));
            Assert.IsTrue(origOrNew(t1));
            Assert.IsTrue(origOrFalsing(t1));
        }
    }

About Jon Limjap

Jon Limjap has been programming since he was 12 and hasn't stopped yet. He was gone for a while in iOS and Java land, but is now back in .NET searching for unicorns and hunting down dragons.
This entry was posted in Technical Articles and tagged , , , . Bookmark the permalink.

4 Responses to Combining generic predicates in C#

  1. billiam says:

    You are a genius! Such a simple and elegant solution. I wracked my brain for hours trying to come up with an answer on how to easily combine Predicates. It also works for Predicate in the case you’re using a (PagedCollectionView)view.Filter;

  2. billiam says:

    apparently Predicate “” isn’t comment friendly :Þ

  3. billiam says:

    Predicate “less than” object “greater than”

  4. Jon Limjap says:

    Hi billiam,

    Glad I could help :)

Comments are closed.