Search code examples
c#lambdaexpression-trees

Expression trees - parameter not mapped from lambda function argument to Expression Parameter


I am trying to wrap my head around Expression trees and I came to the below issue which I can not resolve. I am trying to generate a simple lambda function to check whether an integer value is even:

        public static Func<int, bool> Generate_IsEven_Func()
        {
            var numParam = Expression.Parameter(typeof(int), "numParam");
            var returnValue = Expression.Variable(typeof(bool), "returnValue");

            var consoleWL = typeof(Console).GetMethod(nameof(Console.WriteLine), new[] { typeof(int) });
            
            var body = Expression.Block(
                 // Scoping the variables
                 new[] { numParam, returnValue },

                 // Printing the current value for numParam
                 Expression.Call(
                     null,
                     consoleWL,
                     numParam
                     ),

                 // Assign the default value to return
                 Expression.Assign(returnValue, Expression.Constant(false, typeof(bool))),

                 // If the numParam is even the returnValue becomes true
                 Expression.IfThen(
                            Expression.Equal(
                                Expression.Modulo(
                                    numParam,
                                    Expression.Constant(2, typeof(int))
                                    ),
                                Expression.Constant(0, typeof(int))
                                ),
                            Expression.Assign(returnValue, Expression.Constant(true, typeof(bool)))
                        ),

                 // value to return
                 returnValue
                );

            var lambda = Expression.Lambda<Func<int, bool>>(body, numParam).Compile();
            return lambda;
        }

When I call the newly created lambda function it appears that the value I pass as an argument is not 'mapped' with the respective expression parameter - numParam. Within the block expression I make a call to the Console.WriteLine method to check the current value of numParam and it is 0 every time:

  var isEvenMethod = Generate_IsEven_Func();
  var cond = isEvenMethod(21);
  Console.WriteLine(cond);

  // Prints:
  // 0
  // True

Solution

  • You should not include numParam in the array of variables you're passing as the first parameter to Expression.Block(...) - right now you're essentially creating a new numParam variable within the block that is unrelated to the numParam parameter passed to the lambda. Since the variable is automatically initialized with the default value for int (0), that explains the output you're seeing.