Подтвердить что ты не робот

С# отрицает выражение

Я ищу способ отрицать выражение, используемое для фильтрации последовательностей 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), возможно).

4b9b3361

Ответ 1

Легкий метод расширения:

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

Ответ 2

Публикация для справок в будущем.

Ответ Дэнни Чена может быть более общим:

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.

Ответ 3

Как насчет этого?

Expression<Func<bool>> expr = () => true;
Expression<Func<bool>> negated = () => !expr.Compile()();