Lambda编译失败,引用在"范围"中定义,但未定义

one*_*e-t 5 c# expression-trees

在下面的简单代码段中:

static void Main(string[] args)
{
    Expression<Func<string, bool>> equal = s => s == "test";
    LambdaExpression lambda = Expression.Lambda(equal.Body, Expression.Parameter(typeof(string), "s"));
    lambda.Compile();
}
Run Code Online (Sandbox Code Playgroud)

编译方法失败了 InvalidOperationException

"范围''引用的'System.String'类型的变量'',但未定义".

虽然我发现了其他类似的问题,但我无法理解所提供的答案.

LambdaExpression的DebugView包含:

.Lambda #Lambda1<System.Func`2[System.String,System.Boolean]>(System.String $s) {
    $s == "test"
}
Run Code Online (Sandbox Code Playgroud)

那么,我在这个问题上的其他例子已经看到,参数和使用不匹配,这并不出现在这里是一个问题.我究竟做错了什么?

svi*_*ick 9

lambda表达式的参数不使用基于名称的相等性,它们使用引用相等性.因此,在您的表达式中,您有两个完全不同的参数被调用s,一个被定义但未被使用,另一个被使用但未被定义.

所以,基本上,你的表达式是这样的s1 => s2 == "test",这就是它无法编译的原因.最简单的解决方法是使用原始表达式使用的相同参数:

LambdaExpression lambda = Expression.Lambda(equal.Body, equal.Parameters.Single());
Run Code Online (Sandbox Code Playgroud)

如果您真的想使用自己的参数,则需要使用新参数替换lambda正文中原始参数的所有实例.可能最好的方法是使用ExpressionVisitor.