Well, the following code is self-explaining; I want to combine two expressions into one using And
operator. The last line causes rune-time the error:
Additional information: variable 'y' of type 'System.String' referenced from scope '', but it is not defined
Code:
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
The problem is that parameter expression objects that represents variable
y
in expressionse1
ande2
are different. The fact that the two variables are named the same and have the same type does not matter:e1.Parameters.First()
ande2.Parameters.First()
is not the same object.This causes the problem that you see: only
e1
's parametery
is available toLambda<>
, whilee2
's parametery
is out of scope.To fix this problem use
Expression
APIs to createe1
ande2
. This way you would be able to share the parameter expression across them, thus eliminating the problem of scope.As indicated in the other answer, you have two expressions where both have a parameter named
y
. Those don't automatically relate to each other.To properly compile your expression, you need to specify both source expression's parameters:
Of course, you'd want an expression that combines both expressions with only one parameter. You can rebuild the expressions like this:
As for your comment that you don't want to rebuild the expression, but do it on an existing expression's body and parameters: this works using
ExpressionRewriter
from Combining two lambda expressions in c# andAndAlso
from Replacing the parameter name in the Body of an Expression:Thanks everybody collaborated.
As dasblinkenlight pointed out the two parameters in the two expressions are not the same. Reason? Well, it is the compiler trick. When compiling, it creates a class for each expression and name each parameter something like xxx1, xxx2,... completely different from the original names.
And the answer for .Net 4.0+:
How to Combine two lambdas