我只是去那里把它做为一个傻答案。只是要清楚:我不会这样做,我不建议任何人这样做。 :)
我有点想看看是否有可能得到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));
}
}
首先,!
运算符重载执行函数否定(就像在this answer中一样),然后隐式转换运算符为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>'来使它与像Entity Framework这样的Linq2Entities提供程序一起工作。 –
@ScottChamberlain:我可以用表达式来完成它,但我不知道它是否会转化为实体的兼容_runtime_执行(我想它_might_,毕竟,对SQL查询有什么额外的否定?)。也许在业余时间,我会给它一个镜头。 –
如果您想将lambda转换为相反的值,可以使用变量'Expression> originalLambda','Expression > negatedLambda = originalLambda.Update(Expression.Not(originalLambda.Body),originalLambda .Parameters);' –