PredicateBuilder methods clarification
I lo开发者_C百科oked 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?
I believe it's a typing issue: Expression.OrElse
returns a plain Expression, not an Expression<Func<T, bool>>
.
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.
精彩评论