Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/311.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在父表达式中重用表达式结果_C#_Expression Trees - Fatal编程技术网

C# 在父表达式中重用表达式结果

C# 在父表达式中重用表达式结果,c#,expression-trees,C#,Expression Trees,假设我有一个结合了两个子表达式(所有表达式将返回一个int)的函数,根据规则“ab+a”: 如果我编译并运行结果的表达式,编译器是否足够聪明,知道参数a不需要在内部显式计算两次?a和b的表达式树可能非常冗长且昂贵 事实上,如果生成的表达式将对a求值两次,那么缓存该值以供重用的最佳方法是什么 例如,我想知道这是否可行(但我不清楚ConstantExpression是否可以保存运行时确定的表达式结果): 注意:我知道这可能会被重构为“a(b+1)”,但我最初的问题成立,因为我有其他组合,它们可能会以

假设我有一个结合了两个子
表达式
(所有
表达式
将返回一个
int
)的函数,根据规则“ab+a”:

如果我编译并运行结果的
表达式
,编译器是否足够聪明,知道参数
a
不需要在内部显式计算两次?
a
b
表达式
树可能非常冗长且昂贵

事实上,如果生成的
表达式
将对
a
求值两次,那么缓存该值以供重用的最佳方法是什么

例如,我想知道这是否可行(但我不清楚
ConstantExpression
是否可以保存运行时确定的
表达式结果):


注意:我知道这可能会被重构为“a(b+1)”,但我最初的问题成立,因为我有其他组合,它们可能会以类似的方式多次重用
a
b
。例如,“a2+ab+b2”。

是的,对于原始表达式,它将被计算两次,但您可以缓存它<代码>表达式。常量在这种情况下不起作用,因为它需要常量值,并且需要在表达式执行期间对其求值,但您可以使用
Expression.Variable
声明新变量,然后使用
Expression.Assign
值保存到该变量,然后使用这些表达式声明
Expression.Block
,因为
变量
需要自己的块。 如果需要,可以对
b
变量执行相同的操作

以下代码将生成此类表达式:

(obj) => { int cached = obj.A; return cached*obj.B + cached; }
以下是示例代码:

using System;
using System.Linq.Expressions;

public class Program
{
    public static void Main(string[] args)
    {
        ParameterExpression param = Expression.Parameter(typeof(Test), "obj");
        Expression a = Expression.Property(param, "A");
        Expression b = Expression.Property(param, "B");
        Expression result = CustomCombine(a, b);

        var lambda = Expression.Lambda<Func<Test, int>>(result, new ParameterExpression[] { param });
        Func<Test, int> func = lambda.Compile();

        var obj = new Test();
        var val = func(obj);

        Console.WriteLine("Result is " + val);
    }

    private static Expression CustomCombine(Expression a, Expression b)
    {
        var variable = Expression.Variable(a.Type, "cached");
        var aVal = Expression.Assign(variable, a);

        var mult = Expression.Multiply(variable, b);
        var result = Expression.Add(mult, variable);
        // here we are making Block with variable declaration and assigment
        var block = Expression.Block(new ParameterExpression[]{variable}, aVal, result);
        return block;
    }
}

public class Test
{
    public int A
    {
        get
        {
            Console.WriteLine("Property A is accessed");
            return 42;
        }
    }

    public int B
    {
        get
        {
            return 1;
        }
    }
}
使用系统;
使用System.Linq.Expressions;
公共课程
{
公共静态void Main(字符串[]args)
{
ParameterExpression param=表达式参数(typeof(Test),“obj”);
表达式a=表达式属性(参数“a”);
表达式b=表达式属性(参数“b”);
表达式结果=自定义组合(a,b);
var lambda=Expression.lambda(结果,新参数Expression[]{param});
Func Func=lambda.Compile();
var obj=新测试();
var val=func(obj);
Console.WriteLine(“结果为”+val);
}
私有静态表达式CustomCombine(表达式a、表达式b)
{
var variable=Expression.variable(a.Type,“cached”);
var aVal=表达式.Assign(变量,a);
var mult=表达式。乘法(变量,b);
var result=Expression.Add(mult,variable);
//这里我们用变量声明和赋值来生成块
var block=Expression.block(新参数Expression[]{variable},aVal,result);
返回块;
}
}
公开课考试
{
公共INTA
{
得到
{
Console.WriteLine(“访问了属性A”);
返回42;
}
}
公共int B
{
得到
{
返回1;
}
}
}

还有工作。NetFiddle示例-

谢谢,这正是我想要的。
(obj) => { int cached = obj.A; return cached*obj.B + cached; }
using System;
using System.Linq.Expressions;

public class Program
{
    public static void Main(string[] args)
    {
        ParameterExpression param = Expression.Parameter(typeof(Test), "obj");
        Expression a = Expression.Property(param, "A");
        Expression b = Expression.Property(param, "B");
        Expression result = CustomCombine(a, b);

        var lambda = Expression.Lambda<Func<Test, int>>(result, new ParameterExpression[] { param });
        Func<Test, int> func = lambda.Compile();

        var obj = new Test();
        var val = func(obj);

        Console.WriteLine("Result is " + val);
    }

    private static Expression CustomCombine(Expression a, Expression b)
    {
        var variable = Expression.Variable(a.Type, "cached");
        var aVal = Expression.Assign(variable, a);

        var mult = Expression.Multiply(variable, b);
        var result = Expression.Add(mult, variable);
        // here we are making Block with variable declaration and assigment
        var block = Expression.Block(new ParameterExpression[]{variable}, aVal, result);
        return block;
    }
}

public class Test
{
    public int A
    {
        get
        {
            Console.WriteLine("Property A is accessed");
            return 42;
        }
    }

    public int B
    {
        get
        {
            return 1;
        }
    }
}