Can Expression.Block() return a value within a lambda closure?

.net, c#, expression-trees

Solution

Without a good Minimal, Complete, and Verifiable code example, and especially without specifics about what `ExpressionA()` and `ExpressionB()` are and how you're actually using them, it's impossible to know for sure what the best answer might be. However, the most apparent issue I see is that you are re-declaring `inputArray`, which creates a new local variable in the block. Having not been assigned to anything, its value is of course `null`.

The fix would be to just remove that from the block's variables, leaving only `xformArray`:

Func<double[], double> compiled = Expression.Lambda<Func<double[], double>>(
    Expression.Block(new ParameterExpression[] { xformArray },
        Expression.Assign(xformArray, ExpressionA(inputArray)),
        ExpressionB(xformArray)),
    inputArray).Compile();

Again, without a good MCVE, it's impossible to know for sure what your options might be. But IMHO it is always preferable to express expressions in code instead of building them manually. E.g.:

Func<double[], double> MakeExpression(
    Func<double[], double[]> transformA,
    Func<double[], double> transformB)
{
    return a => transformB(transformA(a));
}

If the transforms themselves are for some reason required to be expressed as expressions, you can still compile them individually before building the rest of the lambda:

Func<double[], double> MakeExpression(
    Expression<Func<double[], double[]>> transformA,
    Expression<Func<double[], double>> transformB)
{
    Func<double[], double[]> transformACompiled = transformA.Compile();
    Func<double[], double> transformBCompiled = transformB.Compile();

    return a => transformBCompiled(transformACompiled(a));
}

But, if you must do the whole thing using the `Expression` class explicitly, the correction in the first code example above should address your concern.

Finally, I'll point out that your original code can be significantly simplified:

    Func<double[], double> compiled = Expression.Lambda<Func<double[], double>>(
        ExpressionB(ExpressionA(inputArray)),
        inputArray).Compile();

Of course, in your real code you may have a more complicated expression. But at least for the example in your post, you don't even need the block or the intermediate local variable.

Problem

I'd like to compile two separate expression trees into a single compiled lambda. I have a `double[]` input array. The first expression tree (for the sake of simplicity, let's refer to as `ExpressionA`) creates a new `double[]` array of the same length, which contains the results of a transformation of the input array values. The second expression tree (`ExpressionB`) does some calculations on the transformed array and returns a single `double` output, which I'd like to return. I thought the following would work, but I am having problems: ``` ParameterExpression inputArray = Expression.Parameter(typeof(double[])); ParameterExpression xformArray = Expression.Parameter(typeof(double[])); Func<double[], double> compiled = Expression.Lambda<Func<double[], double>>( Expression.Block(new ParameterExpression[] { inputArray, xformArray }, Expression.Assign(xformArray, ExpressionA(inputArray)), ExpressionB(xformArray)), inputArray).Compile(); ``` Although the program builds, I get a NullReference runtime exception when I called the compiled function (stack trace isn't helpful since it doesn't get inside `lambda_method()`). However, this simpler version runs just fine (just passing in the xformed array): ``` Func<double[], double> compiled = Expression.Lambda<Func<double[], double>>( ExpressionB(xformArray)), xformArray).Compile(); ``` But this simpler version also fails with the NullReference exception: ``` Func<double[], double> compiled = Expression.Lambda<Func<double[], double>>( Expression.Block(new ParameterExpression[] { xformArray }, ExpressionB(xformArray)), xformArray).Compile(); ``` Lastly, I also tried this proof-of-concept version and it also works (leading me to believe that a `Block` should conceptually be OK inside a lambda): ``` Func<double[], double> compiled = Expression.Lambda<Func<double[], double>>( Expression.Block(new ParameterExpression[] { inputArray, xformArray }, Expression.Constant(0.0)), // stub test inputArray).Compile(); ``` So my question is how do I use both expression trees in a sequential manner inside a single compiled lambda?

Original source