C # отрицает выражение - PullRequest
       25

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

20 голосов
/ 11 декабря 2010

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

Ответы [ 3 ]

19 голосов
/ 11 декабря 2010

Простой метод расширения:

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
1 голос
/ 09 августа 2017

Отправка для дальнейшего использования.

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

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.

0 голосов
/ 11 декабря 2010

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

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