variable ” of type ” referenced from scope ”, but it is not defined

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:

Expression<Func<string, bool>> e1 = (y => y.Length > 0);
Expression<Func<string, bool>> e2 = (y => y.Length < 5);

var e3 = Expression.And(e1.Body, e2.Body);

// (string, string) by adding both expressions' parameters.
var e4 = Expression.Lambda<Func<string, string, bool>>(e3, new[] 
{ 
    e1.Parameters[0], 
    e2.Parameters[0] 
});

Func<string, string, bool> compiledExpression = e4.Compile();

bool result = compiledExpression("Foo", "Foo");

Of course, you’d want an expression that combines both expressions with only one parameter. You can rebuild the expressions like this:

ParameterExpression param = Expression.Parameter(typeof(string), "y");
var lengthPropertyExpression = Expression.Property(param, "Length");

var e1 = Expression.GreaterThan(lengthPropertyExpression, Expression.Constant(0));
var e2 = Expression.LessThan(lengthPropertyExpression, Expression.Constant(5));

var e3 = Expression.AndAlso(e1, e2);

var e4 = Expression.Lambda<Func<string, bool>>(e3, new[] { param });

Func<string, bool> compiledExpression = e4.Compile();

bool result = compiledExpression("Foo");

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# and AndAlso from Replacing the parameter name in the Body of an Expression:

Expression<Func<string, bool>> e1 = (y => y.Length > 0);
Expression<Func<string, bool>> e2 = (z => z.Length < 10);

var e3 = ParameterReplacer.AndAlso<string>(e1, e2);

Func<string, bool> compiledExpression = e3.Compile();

bool result = compiledExpression("Foo");

Leave a Comment