linq 表达式的惰性求值

问题描述 投票:0回答:1

我正在尝试构建一个表达式评估器 Linq 表达式。我正在努力做到这一点 所有函数参数都是惰性求值的,但不能完全求值 到达那里。

我在这里写的是假的,但真实的事情是 linq 表达式。

示例表达式:

Func1(Func2(10) + 1, Func3(10))

更新

Expression.Call(Func1,
    Expression.Add(
        Expression.Call(Func2, Expression.Constant(10)),
        Expression.Constant(1))
    Expression.Call(Func3, Expression.Constant(10))
)

我希望 Func1 的参数在调用时进行评估 也就是说,我希望对参数进行惰性评估。包裹的时候是可以的 lambda 表达式内的参数表达式,但如果我这样做,则二进制表达式 Func2(10) + 1 将失败,因为无法将 lambda 添加到常量表达式。

实际的功能代码如下所示:

  int Func1(Func<int> arg1, Func<int> arg2)
  {
  }

arg1 运行时将计算“Func2(10) + 1”
arg2 运行时将计算“Func3(10)”

所以在这里我可以选择是否要评估论证,以获得惰性效果。

这可以实现吗?

lambda lazy-evaluation
1个回答
3
投票

首先,我认为首先讨论不使用表达式树的问题会很有帮助。你说这是你要调用的函数:

int Func1(Func<int> arg1, Func<int> arg2)
{
}

您想弄清楚如何使用表达式树实现以下内容吗?

Func1(() => Func2(10) + 1, () => Func3(10));

到目前为止这是正确的吗?如果这都是真的,那么考虑这个类:

class Program
{
    public static void Main(string[] args)
    {
        Console.WriteLine(Func1(() => Func2(10) + 1, () => Func3(10)));            

        var arg1 = Expression.Add(Expression.Call(typeof(Program), "Func2", Type.EmptyTypes, Expression.Constant(10)), Expression.Constant(1));
        var arg2 = Expression.Call(typeof(Program), "Func3", Type.EmptyTypes, Expression.Constant(10));
        var callFunc1 = Expression.Call(typeof(Program), "Func1", Type.EmptyTypes, Expression.Lambda<Func<int>>(arg1), Expression.Lambda<Func<int>>(arg2));
        var tester = Expression.Lambda<Func<int>>(callFunc1);
        int result = tester.Compile()();

        Console.WriteLine(result);
    }

    static int Func1(Func<int> arg1, Func<int> arg2)
    {
        return arg1() + arg2();
    }

    static int Func2(int arg)
    {
        return arg;
    }

    static int Func3(int arg)
    {
        return 2 * arg;
    }
}

它将两次打印出

31
(10 + 1) + (10 * 2)
。第一个是直接调用它,第二个使用表达式树。

© www.soinside.com 2019 - 2024. All rights reserved.