Search code examples
c#expressionexpression-trees

C# Wrap array initialization with AsParallel - Expression Trees


How can I wrap NewArrayExpression with ParallelEnumerable.AsParallel ?

for example I have Expression what represent next code:

var data = new int {1, 2, 3, 4, 5};

the result what I want to get:

var data = new int {1, 2, 3, 4, 5}.AsParallel();

I try use ExpressionVisitor and VisitNewArray method:

    protected override Expression VisitNewArray(NewArrayExpression node)
    {

            var source = Expression.Parameter(typeof(IEnumerable<>).MakeGenericType(typeof(MethodCallExpression)), "source");

            var asParallel =
                Expression.Call(
                    typeof(ParallelEnumerable),
                    nameof(ParallelEnumerable.AsParallel),
                    new[] { typeof(ParallelQuery<MethodCallExpression>) },
                    source
                );

            return ***???***
    }

But don't known how to right "wrap" node.Expressions this Expression.Call

Thanks for any suggestions!


Solution

  • Doing so will change the expression type form T[] to ParallelQuery<T> which may cause issues.

    But answering your concrete question. Let rewrite your example

    var data = new int[] {1, 2, 3, 4, 5}.AsParallel();
    

    as follows

    var newArray = new int[] { 1, 2, 3, 4, 5 };
    var data = newArray.AsParallel();
    

    Now taking into account that AsParallel is generic static extension method, the actual call after removing the compiler sugar is

    var data = ParallelEnumerable.AsParallel<int>(newArray);
    

    In other words, calling the generic static method passing array element type as generic type argument and the new array expression as argument. e.g.

    protected override Expression VisitNewArray(NewArrayExpression node)
    {
        var asParallel = Expression.Call(
            typeof(ParallelEnumerable),
            nameof(ParallelEnumerable.AsParallel),
            new [] { node.Type.GetElementType() },
            node
        );
        return asParallel;
    }