Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Expression tree library ignores short-circuit evaluation concept

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?

like image 467
jwaliszko Avatar asked Feb 12 '23 13:02

jwaliszko


1 Answers

Expression.And represents the non-short circuiting AND operator (&).

Expression.AndAlso represents the short circuiting AND operator (&&).

like image 62
Servy Avatar answered Feb 15 '23 09:02

Servy