当我写如下lambda表达式时:
Expression<Func<string, bool>> e1 = y => y.Length < 100;
Expression<Func<string, bool>> e2 = y => y.Length < 200;
var e3 = Expression.And(e1.Body, e2.Body);
var e4 = Expression.Lambda<Func<string, bool>>(e3, e1.Parameters.ToArray());
e4.Compile(); // <--- causes run-time error
会报如题目的错误。variable '' of type '' referenced from scope '', but it is not defined
原因是两个表达式的条件并不是针对同一对应指定的。所以当使用And 或者 OR时两个表达式并列使用时会有问题,解决办法看我的另一篇文章。
有详细说明:https://lebang2020.cn/details/20090710uf5gw2.html
报错根因与正确做法
这个运行时错误的根因:e1 与 e2 两个 lambda 各自的参数表达式是不同的对象(哪怕都叫 y),Expression.And 直接把两段 Body 拼在一起时,第二个 Body 里的参数在最终表达式的参数表里"查无此人",编译时就抛 variable referenced from scope。
- 正确做法:两段表达式共用同一个 ParameterExpression 实例(创建一次,两处使用);
- 已有两个独立表达式时,用一个 ExpressionVisitor 把第二段的参数重绑到第一段的参数;
- 拼接条件的需求可考虑直接引用 LinqKit 的 PredicateBuilder,And/Or 语义齐全;
- 调试技巧:打印表达式 ToString,能看到两处参数名是否一致(如 (y, y1) 就是问题征兆)。