How does LinqKit PredicateBuilder join Expressions together?

I’m using LinqKit 1.2.3 and I was just trying out how to combine multiple expressions.
Basically what I wanted to achieve is "give me results which match A && B && (C || D)".

I made the bellow code as an example:

string[] values = new string[]
{
    "1","2","3","11","56",
    "2","543","345","13421","562467",
    "14324","23452","36789","10001","556876",
    "1234","2432423","36456456","187681","50006",
};

ExpressionStarter<String> masterPredicate = PredicateBuilder.New<String>(true);
ExpressionStarter<String> andPredicate = PredicateBuilder.New<String>(true);
ExpressionStarter<String> orPredicate = PredicateBuilder.New<String>(true);

//andPredicate.And(x => x.StartsWith('1')).And(x => x.EndsWith('1')); // doesn't work ???
andPredicate.And(x => x.StartsWith('1'));
andPredicate.And(x => x.EndsWith('1'));

//orPredicate.Or(x => x.Contains('6')).Or(x => x.Contains('0')); // doesn't work ???
orPredicate.Or(x => x.Contains('6'));
orPredicate.Or(x => x.Contains('0'));

//master.And(andPredicate).And(orPredicate); // doesn't work ???
masterPredicate.And(andPredicate);
masterPredicate.And(orPredicate);

string[] filtered = values.Where(masterPredicate).ToArray();

foreach (var item in filtered)
{
    Console.WriteLine(item);
}

In the end I got it working, but now I have a question, for example why does

andPredicate.And(x => x.StartsWith('1')).And(x => x.EndsWith('1'));

produce different results then

andPredicate.And(x => x.StartsWith('1'));
andPredicate.And(x => x.EndsWith('1'));

As a matter of fact none of the commented out lines worked the way I thought they would. Can someone shed some light on why this is?

>Solution :

This is expected. PredicateBuilder.And returns a new expression, it doesn’t modify the existing one. andPredicate doesn’t change. andPredicate.And(x => x.StartsWith('1')) returns a new expression that’s never used.

var predicate=andPredicate.And(x => x.StartsWith('1')).And(x => x.EndsWith('1'));

is equivalent to :

var pred1=andPredicate.And(x => x.StartsWith('1'));
var predicate=pred1.And(x => x.EndsWith('1'));

Leave a Reply