Lambda compile failure, reference defined in '' scope, but is not defined

c# expression-trees

Question

In the simple snippet below:

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();
}

The compile method fails with an InvalidOperationException

"variable 's' of type 'System.String' referenced from scope '', but it is not defined".

While I've found other similar questions, I've failed to understand the answers provided.

The DebugView of the LambdaExpression contains this:

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

So where I've seen in other examples of this question, the parameter and the usage don't match up, this doesn't appear to be an issue here. What am I doing wrong?

Accepted Answer

Parameters of lambda expressions don't use equality based on names, they use reference equality. So, in your expression, you have two entirely different parameters called s, one is defined but not used, the other is used but not defined.

So, basically, your expression is something like s1 => s2 == "test", which is why it fails to compile. The simplest fix would be to use the same parameter the original expression uses:

LambdaExpression lambda = Expression.Lambda(equal.Body, equal.Parameters.Single());

If you really wanted to use your own parameter, you would need to replace all instances of the original parameter in the lambda body with your new parameter. Probably the best way to do that is to use ExpressionVisitor.



Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why