此方法应返回一个函数,该函数可以计算两个大小相同的向量的标量积:
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();
}
但为了做到这一点,我需要知道数组的长度,有一个方法Expression.ArrayLength()
返回UnaryExpression
而不是int
,并且表达式不能显式地转换为int,有没有一种方法可以事先将数组长度计算为int
?
统一采购司
下面是一个单元测试,展示了该方法的工作原理:
[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);
}
3条答案
按热度按时间qyyhg6bp1#
数组的长度不是类型定义的一部分,它是一个只能在运行时获得的值。
随着最近Generic Math的引入,您可以使用泛型进行乘法和加法运算,而无需构建表达式树;
但是我假设对于您的任务,您需要构建一个与上述方法等效的表达式树,然后编译它。
jc3wubiy2#
这可能不是你想要的,但如果你只需要保留签名,这似乎可以解决你的问题:
afdcj2ne3#
代码中唯一需要表达式树的部分(假设您不能像其他两种解决方案那样使用通用数学或动力学)是运算符(加和乘)。
如果您单独编译运算符表达式,那么您就可以非常容易地使用LINQ,就像您最初的方法一样-类似于: