I'm just going to throw this out there as a silly answer. Just to be clear: I would not do this, and I do not recommend that anyone does this. :)
I kind of wanted to see if it was possible to get the somelist.Where(!expr)
syntax or something like it.
Well I succeeded, and I hate myself.
var expr = N.egatable<MyClass>(x => x.Prop != 1);
somelist = someList.Where(!expr);
The N.egatable
was just a small convenience syntax helper and largely unnecessary (EDIT: I wanted to avoid having to explicitly define MyClass
or somehow make the instantiation of the object wrapper hidden, but couldn't quite get there and thought maybe someone would have a better idea):
public static class N
{
public static Negator<T> egatable<T>(Func<T, bool> underlyingFunction)
{
return new Negator<T>(underlyingFunction);
}
}
Negator<T>
is where the real "magic" happens:
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));
}
}
First the !
operator overload performs the function negation (just as in this answer), then the implicit conversion operator to Func<T, bool>
lets it pass in to the Where
extension method.
Perhaps very silly is you can keep flipping it back and forth like this:
somelist = someList.Where(!!expr);
somelist = someList.Where(!!!expr);
somelist = someList.Where(!!!!expr);
somelist = someList.Where(!!!!!expr);
somelist = someList.Where(!!!!!!expr); //oh my what
So again... please don't do this. :) Definitely stick to the proper/sane way of doing things as in Steven's answer.
EDIT: Here's an implementation using expressions which works the exact same way in terms of syntax usage. Not sure if it's "correct", and haven't tested it against 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);
}
}