Home > Back-end >  How to get the array length of an expression parameter
How to get the array length of an expression parameter

Time:01-16

This method should return a function which can evaluate the scalar product of two vectors of the same size:

public static Func<T[], T[], T> GetVectorMultiplyFunction<T>() where T : struct
{
    var x = Expression.Parameter(typeof(T[]), "x");
    var y = Expression.Parameter(typeof(T[]), "y");


    var body = Enumerable
        .Range(0, 3 /*Expression.ArrayLength(x)*/)
        .Select(i => Expression.Multiply(
            Expression.ArrayIndex(x, Expression.Constant(i)),
            Expression.ArrayIndex(y, Expression.Constant(i))
        ))
        .Aggregate(Expression.Add);

    var lambda = Expression.Lambda<Func<T[], T[], T>>(body, x, y);

    return lambda.Compile();
} 

But in order to do that, I need to know the length of an array. There's a method Expression.ArrayLength() which returns UnaryExpression instead of the int and the expression cannot be cast explicitly to int. Is there a way of evaluating the array length as int beforehand?

UPD

Here's a unit test showing how this method should work:

[Test]
public void GetVectorMultiplyFunctionReturnsFunctionForInt()
{
    var first = new int[] { 1, 2, 3 };
    var second = new int[] { 2, 2, 2 };
    var expected = 1 * 2   2 * 2   3 * 2;
    var func = GetVectorMultiplyFunction<int>();
    var actual = func(first, second);
    Assert.AreEqual(expected, actual);
}

CodePudding user response:

This may not be what you want but seems to solve your problem if all you need to retain is the signature:

public static Func<T[], T[], T> GetVectorMultiplyFunction<T>() where T : struct
{
     return (T[] x, T[] y) => {
     T result = default(T);      

     for(var i = 0; i < x.Length; i  )
     {
         var xd = (dynamic)x[i];
         var yd = (dynamic)y[i];
         result  = (xd * yd);
     }
     
     return result;
};

CodePudding user response:

The length of an array is not part of the type definition, it's a value you can only obtain at runtime.

With the recent introduction of Generic Math, you can multiply and add values using generics without needing to build an expression tree;

public static T Calc<T>(T[] x, T[] y)
    where T : struct, IMultiplyOperators<T,T,T>, IAdditionOperators<T,T,T>
{
     T result = default(T);

     for(var i = 0; i < x.Length && i < y.Length; i  )
         result  = x[i] * y[i];

     return result;
}

But I assume that for your assignment you are expected to build an expression tree equivalent to the above method, then compile it.

  • Related