【发布时间】:2014-07-10 20:16:45
【问题描述】:
请看以下概念证明:
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
因为第一个操作数的计算结果为假,所以无论第二个操作数的值是什么,AND 运算的结果都是假的。这就是为什么不应该计算第二个操作数的原因。虽然 C# 编译器可以正确执行此操作,但表达式库却没有。
如何修复我的代码以遵守短路评估?
【问题讨论】:
-
您可以为自己省去很多麻烦,并使用 lambda 来创建这样的表达式,而不是像以前那样做所有事情。它更快、更容易,并且会生成正确的表达式。
标签: c# .net expression-trees