【问题标题】:How to create "System.Linq.Expression" expression dynamically with parentheses如何使用括号动态创建“System.Linq.Expression”表达式
【发布时间】:2015-03-08 05:18:16
【问题描述】:

我需要动态创建表达式。我的问题是如何在 System.Linq.Expression 中添加括号来处理优先级...

int a = 1, b = 1, c = 1, d = 2;

我已经转换了下面的表达式

 var v = a > 1 || b > 1 && c > 1 || d > 1;
 Expression case1Expr =

                Expression.AndAlso(
                Expression.OrElse(
                Expression.GreaterThan(Expression.Parameter(typeof(int), "a"), Expression.Constant(1)),
                Expression.GreaterThan(Expression.Parameter(typeof(int), "b"), Expression.Constant(1))),


                Expression.OrElse(
                Expression.GreaterThan(Expression.Parameter(typeof(int), "c"), Expression.Constant(1)),
                Expression.GreaterThan(Expression.Parameter(typeof(int), "d"), Expression.Constant(1))));

但是如何用括号转换一个,

var v2 = (a > 1 || b > 1) && (c > 1 || d > 1);

【问题讨论】:

    标签: c# linq dynamic expression


    【解决方案1】:

    只是为了扩展其他答案;括号是我们需要的,以防止我们用来描述方程(A OP B)的中缀符号不明确。其他符号,例如 postfix (A B OP),不需要它。

    在您的情况下,您正在组合一个表达式树,这也是明确的,即只有一种解释它的方式。所以表达式树中没有括号的概念。树的“形状”决定了操作的顺序。

    【讨论】:

      【解决方案2】:

      您可以通过构建表达式树的方式来指定优先级。 && 运算符通常优先于 || 运算符,因此您的转换将应用于带括号的表达式。否则就是:

      var v = a > 1 || b > 1 && c > 1 || d > 1;
      
      OrElse(
          GreaterThan(a > 1),
      
          OrElse(
            AndAlso(
              GreaterThan(b > 1),
              GreaterThan(c > 1)),
            GreaterThan(d > 1)))
      

      【讨论】:

        【解决方案3】:

        您已经拥有的代码具有这些语义。当您在您拥有的确切代码上调用 ToString 时,您会得到:

        (((a > 1) OrElse (b > 1)) AndAlso ((c > 1) OrElse (d > 1)))
        

        不需要特定的表达式来表示括号;括号隐含在您编写表达式的方式中。在您的代码中,您将Or 表达式传递给And 表达式,因此Or 表达式将被括起来。

        【讨论】:

          【解决方案4】:

          我可能错过了你的问题,但你不会这样做:

          Expression first = Expression.OrElse(
              Expression.GreaterThan(Expression.Parameter(typeof(int), "a"), Expression.Constant(1)),
              Expression.GreaterThan(Expression.Parameter(typeof(int), "b"), Expression.Constant(1)));
          
          Expression second = Expression.OrElse(
              Expression.GreaterThan(Expression.Parameter(typeof(int), "c"), Expression.Constant(1)),
              Expression.GreaterThan(Expression.Parameter(typeof(int), "d"), Expression.Constant(1)));
          
          Expression final = Expression.AndAlso(first, second);
          

          结果:(((a > 1) OrElse (b > 1)) AndAlso ((c > 1) OrElse (d > 1)))

          【讨论】:

          • 这正是 OP 已经在做的事情;没有必要将值放在命名变量中。
          • 问完问题我也意识到了,试试看
          • @Servy 同意。为了清楚起见,我只是将其分解。米兰,您可能想删除问题,因为您已经有了解决方案! :)
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多