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