Lambda linq表达式的延迟求值

Lambda linq表达式的延迟求值,lambda,lazy-evaluation,Lambda,Lazy Evaluation,我正在尝试用 Linq表达式。我想让它这样 所有函数参数都是惰性计算的,但不能完全 到那里 我在这里写的是psuedo,但真实的情况是 linq表达式 示例表达式: Func1(Func2(10) + 1, Func3(10)) 更新 Expression.Call(Func1, Expression.Add( Expression.Call(Func2, Expression.Constant(10)), Expression.Constant(1))

我正在尝试用 Linq表达式。我想让它这样 所有函数参数都是惰性计算的,但不能完全 到那里

我在这里写的是psuedo,但真实的情况是 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)
  {
  }
int Func1(Func arg1,Func arg2)
{
}
运行时arg1将计算“Func2(10)+1”
arg2运行时将计算“Func3(10)”

因此,在这里,我可以选择是否要计算参数,以获得惰性效果


这可能实现吗?

首先,我认为在不使用表达式树的情况下先讨论这个问题会有所帮助。您说过这是您要调用的函数:

int Func1(Func<int> arg1, Func<int> arg2)
{
}
到目前为止这是正确的吗?如果这都是真的,那么考虑这个类:

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;
    }
}
类程序
{
公共静态void Main(字符串[]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(arg1),Expression.Lambda(arg2));
var tester=Expression.Lambda(callFunc1);
int result=tester.Compile();
控制台写入线(结果);
}
静态int Func1(Func arg1,Func arg2)
{
返回arg1()+arg2();
}
静态int Func2(int arg)
{
返回arg;
}
静态int Func3(int arg)
{
返回2*arg;
}
}

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

我认为真正的表达式树代码将比您的伪代码有所改进。@Kirk:好的,我来编辑我的帖子。谢谢您的编辑。但我很困惑,为什么你认为这还没有被懒散地评估?在调用
Func1
之前,不会计算表达式
Func2(10)+1
。我遗漏了什么?@Kirk:但这就是问题所在,当调用Func1时,所有参数都将被计算,我不希望发生这种情况。正如您在我的代码中所看到的,我希望选择调用/求值的参数,这就是为什么我使用Func arg1而不是int arg1。我想我已经开始理解了。我会发布一个答案,这样我可以写出一些格式化的代码,我们可以在那里继续讨论。是的,这是正确的。我希望我的所有函数都是这样的。谢谢,这看起来很有趣,明天我们将进一步研究。表达式树是不变的。因此,下一步是创建一个表达式树访问者,它将任何非函数调用节点复制到一个新树中,并将任何函数调用节点转换为调用这些函数调用节点的lambda表达式调用。对吗?
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;
    }
}