26

我正在寻找一种方法来否定用于过滤IQueryable序列的表达式。

所以,我有类似的东西:

Expression<Func<T, bool>> expression = (x => true);

现在我希望创建会导致屈服的表达式(x => false)- 所以我基本上想否定expression.

我发现自己的工作方法是这样的:

var negatedExpression = 
   Expression.Lambda<Func<T, bool>> (Expression.Not(expression.Body),
                                     expression.Parameters[0])));

但我几乎可以肯定有更好的方法 - 你能帮我吗?(可能类似于Not(expression))。

4

3 回答 3

26

一个简单的扩展方法:

public static Expression<Func<T, bool>> Not<T>(this Expression<Func<T, bool>> one)
{
    var candidateExpr = one.Parameters[0];
    var body = Expression.Not(one.Body);

    return Expression.Lambda<Func<T, bool>>(body, candidateExpr);
}

用法:

Expression<Func<int, bool>> condition = x => x > 5;
var source = Enumerable.Range(1, 10);
var result1 = source.Where(condition.Compile());   //6,7,8,9,10
var result2 = source.Where(condition.Not().Compile());    //1,2,3,4,5
于 2010-12-11T16:06:53.790 回答
3

发布以供将来参考。

丹尼陈的回答可以更通用:

public static Expression<TFunc> Not<TFunc>(this Expression<TFunc> baseExpr)
{
    var param = baseExpr.Parameters;
    var body = Expression.Not(baseExpr.Body);
    var newExpr = Expression.Lambda<TFunc>(body, param);
    return newExpr;
}

此版本可以接收带有任意数量输入参数的表达式。然而,它只增加了一点可用性,因为表达式很可能会被传递给函数IEnumerable.Where

于 2017-08-09T20:36:37.243 回答
-4

那这个呢?

Expression<Func<bool>> expr = () => true;
Expression<Func<bool>> negated = () => !expr.Compile()();
于 2010-12-11T15:56:28.867 回答