Dynamic Linq Expression with return value

c# expression-trees

Question

I need to create a dynamic linq expression an i started work with many examples. I tested some and some work and some not. In this case i want to create a method that looks like :

public bool Check(int intvar)
{
   if ( i > 2 )
     return true;
   else
     return false;
}

Now i have written the following :

LabelTarget returnTarget = Expression.Label("label");
ParameterExpression para = Expression.Parameter(typeof(int), "intvalue");
Expression test = Expression.GreaterThan(para, Expression.Constant(5));
Expression iftrue = Expression.Return(returnTarget, Expression.Constant(true));
Expression iffalse = Expression.Return(returnTarget,                   Expression.Constant(false));
Expression.IfThenElse(test, iftrue, iffalse);

this.TheExpression = Expression.IfThenElse(test, iftrue, iffalse);
Expression.Lambda<Action<int>>(
this.TheExpression,
new ParameterExpression[] { para }
).Compile()(5);

Now it throws InvalidOperationException:

Cannot jump to the label "label"`

What is wrong ? I only need a return true or false.

1
12
5/12/2017 11:55:08 PM

Accepted Answer

You need to change a few things:

  • Put the return label at the bottom of your function in a block expression, as René suggested. This is where your return statement will jump.

  • Declare the Lambda as type Func<int, bool>. Since you want a return value, this needs to be a function, not an action.

  • Declare the returnTarget label as type bool. Since the return value of a block expression is the value of its last statement, the label must be of the correct type.

  • Provide a default value for the final label (= the return value of your function if the label is reached by normal control flow instead of a return statement).

    LabelTarget returnTarget = Expression.Label(typeof(bool));
    ParameterExpression para = Expression.Parameter(typeof(int), "intvalue");
    Expression test = Expression.GreaterThan(para, Expression.Constant(5));
    Expression iftrue = Expression.Return(returnTarget, Expression.Constant(true));
    Expression iffalse = Expression.Return(returnTarget, Expression.Constant(false));
    
    var ex = Expression.Block(
        Expression.IfThenElse(test, iftrue, iffalse),
        Expression.Label(returnTarget, Expression.Constant(false)));
    
    var compiled = Expression.Lambda<Func<int, bool>>(
        ex,
        new ParameterExpression[] { para }
    ).Compile();
    
    Console.WriteLine(compiled(5));     // prints "False"
    Console.WriteLine(compiled(6));     // prints "True"
    
18
12/3/2012 5:14:48 PM

Popular Answer

If you have simple condition statement like this:

if (condition)
    return expression1;
else
    return expression2;

You can transform that into ternary expression: condition ? expression1 : expression2. And then you can create an expression without using Label, Return, or Goto.

Expression condition;
Expression expression1;
Expression expression2;
/* ... */
Expression body = Expression.Condition(
    test:    condition,
    ifTrue:  expression1,
    ifFalse: expression2);


Related Questions





Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow