。ちょうど明確にする:私はこれをしないだろう、と誰もこれを行うことをお勧めしません。 :)
somelist.Where(!expr)
のような構文を得ることができたかどうかを知りたいと思っていました。
私は成功し、自分自身が嫌いです。
var expr = N.egatable<MyClass>(x => x.Prop != 1);
somelist = someList.Where(!expr);
N.egatable
がEDIT(ほんの少しの便利な構文ヘルパーだったと大幅に不要:私はは、明示的にMyClass
を定義したり、何らかの形で隠されたオブジェクトラッパーのインスタンス化を行うことを避けるためにを望んでいたが、非常に得ることができませんでしたそこに、多分誰かが良いアイデアを持っているだろうと思った):
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));
}
}
:本物の「魔法」が起こる場所
public static class N
{
public static Negator<T> egatable<T>(Func<T, bool> underlyingFunction)
{
return new Negator<T>(underlyingFunction);
}
}
Negator<T>
があります
最初に!
演算子オーバーロードが関数の否定を実行すると(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
だから、再び:
おそらく、非常に愚かなあなたは、このように前後にそれをひっくり返す保つことができるです。 :)確かにスティーブンの答えのように物事を行う適切な/元気な方法に固執する。
EDIT:シンタックスの使い方に関してまったく同じように動作する式を使用した実装です。それが「正しい」かどうかわからない、とEntity Frameworkのに対してそれをテストしていない:より多くのあなたを拷問する
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);
}
}
申し訳ありませんが、私はあなたはそれがあまりにも動作するようになるまで、これはおそらくあなたに食べることを知っているので、(私がしてきましたそこ)。 Entity FrameworkのようなLinq2Entitiesプロバイダでも動作させるために、 'Expression> 'で動作させることができるのだろうかと思います。 –
@ScottChamberlain:私はおそらく式でそれを行うことができますが、エンティティの互換性のある_runtime_実行に変換するかどうかはわかりません(おそらく_might_と思われますが、SQLクエリに対していくつかの否定がありますか?多分私の暇な時間に私はそれを撃つだろう。 –
ラムダをその逆に変換したい場合は、変数 'Expression> originalLambda'、' Expression > negatedLambda = originalLambda.Update(Expression.Not(originalLambda.Body)、originalLambda .Parameters); ' –