2

I looked through PredicateBuilder sources and its' implementation makes me curious. Let's look at Or method implementation:

public static Expression<Func<T, bool>> Or<T> (this Expression<Func<T, bool>> expr1,
                                                      Expression<Func<T, bool>> expr2)
  {
    var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression> ());
    return Expression.Lambda<Func<T, bool>>
          (Expression.OrElse (expr1.Body, invokedExpr), expr1.Parameters);
  }

Why does it Invoke new lambda instead of just using OrElse for predicate body?

SiberianGuy
  • 24,674
  • 56
  • 152
  • 266

2 Answers2

4

I believe it's a typing issue: Expression.OrElse returns a plain Expression, not an Expression<Func<T, bool>>.

Rafe
  • 5,237
  • 3
  • 23
  • 26
  • Good point, may be it is just a workaround to get rid off expression type casting (to be able to access to Body property). But it makes expression more difficult... – SiberianGuy Oct 26 '10 at 22:13
0

I'm not 100% sure either, but I think the issue is ensuring that as each expression Func<T,bool> is chained, the parameter, which is an instance of T, is always the same instance for each expression.

In other words, for:

(t1 => t1>5).And(t2 => t2.Color == Blue)

we assume t1 and t2 are referentially equal, but the InvocationExpression ensures they are by essentially saying: "create a new expression that invokes expr2 with the parameter from expr1".

See also PredicateBuilder Revisited where the author, a contributor to Mono, really explicitly checks for the reference equality of the parameter.

mdisibio
  • 3,148
  • 31
  • 47