我查看了PredicateBuilder来源,其实施让我很好奇。我们来看看Or方法的实现:
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);
}
为什么调用新的lambda而不是仅仅使用OrElse作为谓词体?
答案 0 :(得分:4)
我认为这是打字问题:Expression.OrElse
会返回一个简单的表达式,而不是Expression<Func<T, bool>>
。
答案 1 :(得分:0)
我也不是100%肯定,但我认为问题在于确保每个表达式Func<T,bool>
被链接,参数( T 的实例)始终是每个表达式都有相同的实例。
换句话说,对于:
(t1 => t1>5).And(t2 => t2.Color == Blue)
我们假设t1和t2在引用上相等,但InvocationExpression确保它们基本上是这样说:“使用 expr1 中的参数创建一个调用 expr2 的新表达式”
另见PredicateBuilder Revisited作者,Mono的贡献者,真正明确地检查参数的引用相等性。