Please, take a look at following proof of concept:
private class Model
{
public string Data { get; set; }
public bool NonEmpty() { return Data.Length > 0; }
}
private static Func<Model, bool> Compile()
{
var type = typeof(Model);
var expr = Expression.Parameter(typeof(Model));
var subarg1 = Expression.Property(expr, type.GetProperty("Data"));
var subarg2 = Expression.Constant(null);
var arg1 = Expression.NotEqual(subarg1, subarg2);
var arg2 = Expression.Call(expr, type.GetMethod("NonEmpty"));
var tree = Expression.And(arg1, arg2); // Data != null && NonEmpty()
var func = Expression.Lambda<Func<Model, bool>>(tree, expr).Compile();
return func;
}
var model = new Model {Data = null};
var standardTest = model.Data != null && model.NonEmpty(); // returns false
var exprTreeTest = Compile().Invoke(model); // throws null ref exception
Because the first operand evaluates to false, the result of the AND operation is false no matter what the value of second one may be. That's why the second operand shouldn't be computed. While C# compiler does it correctly, expression library does not.
How to fix my code to respect the short-circuit evaluation?
Expression.And
represents the non-short circuiting AND operator (&
).
Expression.AndAlso
represents the short circuiting AND operator (&&
).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With