Func<T, bool> expr = x => x.Prop != 1;
somelist = somelist.Where(expr);
到目前为止,一切都很好。但我想要像这样否定
expr
:somelist = somelist.Where(!expr);
这导致编译错误:无法将!运算符应用于类型为Func<T, bool>的操作数
。
我需要为此创建另一个表达式变量吗?
Func<T, bool> expr2 = x => x.Prop == 1;
Func<T, bool> expr = x => x.Prop != 1;
Func<T, bool> negativeExpr = value => !expr(value);
或者
somelist = somelist.Where(value => !expr(value));
Expression<Func<T, bool>> expr = x => x.Prop != 1;
var negativeExpr = Expression.Lambda<Func<T, bool>>(
Expression.Not(expr.Body),
expr.Parameters);
somelist = somelist.Where(negativeExpr);
public static Func<T, bool> Not<T>(
this Func<T, bool> predicate)
{
return value => !predicate(value);
}
public static Expression<Func<T, bool>> Not<T>(
this Expression<Func<T, bool>> expr)
{
return Expression.Lambda<Func<T, bool>>(
Expression.Not(expr.Body),
expr.Parameters);
}
现在你可以这样做:
somelist = somelist.Where(expr.Not());
我只是随便说一个愚蠢的答案。请明确一点:我不会这样做,也不建议任何人这样做。 :)
我想知道是否有可能使用somelist.Where(!expr)
语法或类似语法。
嗯,我成功了,但我讨厌自己。
var expr = N.egatable<MyClass>(x => x.Prop != 1);
somelist = someList.Where(!expr);
N.egatable
只是一个小型的语法辅助工具,大多数情况下并不必要(编辑:我希望避免明确定义MyClass
或以某种方式使对象包装器的实例化隐藏起来,但并未成功,想着也许有更好的方法):
public static class N
{
public static Negator<T> egatable<T>(Func<T, bool> underlyingFunction)
{
return new Negator<T>(underlyingFunction);
}
}
Negator<T>
是真正的“魔法”所在:
public class Negator<T>
{
private Func<T, bool> UnderlyingFunction;
public Negator(Func<T, bool> underlyingFunction)
{
this.UnderlyingFunction = underlyingFunction;
}
public static implicit operator Func<T, bool>(Negator<T> neg)
{
return v => neg.UnderlyingFunction(v);
}
public static Negator<T> operator !(Negator<T> neg)
{
return new Negator<T>(v => !neg.UnderlyingFunction(v));
}
}
首先,!
运算符重载执行取反功能(就像这个答案中所述),然后隐式转换运算符到 Func<T, bool>
,使其可以传递到 Where
扩展方法中。
也许很傻,但您可以像这样不断地翻转它:
somelist = someList.Where(!!expr);
somelist = someList.Where(!!!expr);
somelist = someList.Where(!!!!expr);
somelist = someList.Where(!!!!!expr);
somelist = someList.Where(!!!!!!expr); //oh my what
public class ExpressionNegator<T>
{
private Expression<Func<T, bool>> UnderlyingExpression;
public ExpressionNegator(Expression<Func<T, bool>> underlyingExpression)
{
this.UnderlyingExpression = underlyingExpression;
}
public static implicit operator Func<T, bool>(ExpressionNegator<T> neg)
{
return neg.UnderlyingExpression.Compile();
}
public static implicit operator Expression<Func<T, bool>>(ExpressionNegator<T> neg)
{
return neg.UnderlyingExpression;
}
public static ExpressionNegator<T> operator !(ExpressionNegator<T> neg)
{
var originalExpression = neg.UnderlyingExpression;
Expression<Func<T, bool>> negatedExpression = originalExpression.Update(
Expression.Not(originalExpression.Body),
originalExpression.Parameters);
return new ExpressionNegator<T>(negatedExpression);
}
}
Expression<Func<T, bool>>
使其与 Linq2Entities 提供程序(如 Entity Framework)一起工作。 - Scott Chamberlainpublic static Func<T, bool> Not(this Func<T, bool> pr) { return v => !pr(v); }
。现在你可以这样做:someList.Where(expr.Not())
,someList.Where(expr.Not().Not())
等等。 - Steven