我只是去那裏把它做爲一個傻答案。只是要清楚:我不會這樣做,我不建議任何人這樣做。 :)
我有點想看看是否有可能得到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);' –