25

I'm seeking for a way to negate an expression used to filter IQueryable sequences.

So, I've got something like:

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

Now I wish to create the expression which would result in yielding (x => false) - so I basically want to negate the expression.

The working method I've found myself works like this:

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

But I'm almost sure there is a better way - could you help me? (something like Not(expression), probably).

Jb Evain
  • 16,611
  • 2
  • 63
  • 66
Yippie-Ki-Yay
  • 20,062
  • 23
  • 85
  • 143

3 Answers3

24

An easy extension method:

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);
}

Usage:

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
Cheng Chen
  • 39,413
  • 15
  • 105
  • 159
  • Well, I do know how to wrap my way to negate a statement into a 'Not' method, but I was actually seeking for an easy way to actually perform the negation *(it does look to me that calling `Expression.Lambda.Blablabla` is a huge overkill).* – Yippie-Ki-Yay Dec 11 '10 at 16:19
  • 2
    Expression Trees are immutable, so you have to create a new lambda. – Jb Evain Dec 11 '10 at 16:31
2

Posting for future reference.

Danny Chen's answer can be made more generic:

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;
}

This version can receive an Expression with any number of input parameters. It only adds a little useability, however, since the Expression would most likely be passed to a function like IEnumerable.Where anyway.

Nathan
  • 440
  • 2
  • 8
-3

What about this?

Expression<Func<bool>> expr = () => true;
Expression<Func<bool>> negated = () => !expr.Compile()();
as-cii
  • 11,939
  • 4
  • 37
  • 43
  • You just turned the input expression into an opaque method call. This doesn't help at all since the purpose of using an expression is that the query provided can understand it. – CodesInChaos Dec 11 '10 at 17:46