Drinking .NET with LaTtEX

.NET, TDD, Software Development and the Philippine IT industry

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 And
            (this Predicate original, Predicate newPredicate)
        {
            return t => original(t) && newPredicate(t);
        }

        public static Predicate Or
            (this Predicate original, Predicate 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 orig = t => t == 1;
            Predicate newPredicate = t => (t + 1) == 2;
            Predicate falsing = t => (t - 1) == -1;

            Predicate origAndNew = orig.And(newPredicate);
            Predicate 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 orig = t => t == 1;
            Predicate newPredicate = t => (t + 1) == 2;
            Predicate falsing = t => (t - 1) == -1;

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

            Assert.IsTrue(orig(t1));
            Assert.IsTrue(origOrNew(t1));
            Assert.IsTrue(origOrFalsing(t1));
        }
    }
Published 02-03-2009 12:50 AM by Jon Limjap
Filed under: , ,