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
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.