LINQ表达树是否适合树木?

时间:2012-01-24 12:47:31

标签: c# linq expression-trees

LINQ表达树是否适当的树,如图,(有针对性或没有,维基百科似乎不太一致)没有循环?以下C#表达式中表达式树的根是什么?

(string s) => s.Length

表达式树看起来像这样,带有“ - >”表示可通过其他节点访问的节点的属性名称。

     ->Parameters[0]
 Lambda---------Parameter(string s)
    \               /
     \->Body       /->Expression
      \           /
      Member(Length)

使用ExpressionVisitor访问LambdaExpression时,将访问ParameterExpression两次。有没有办法使用ExpressionVisitor访问LambdaExpression,以便所有节点只访问一次,并以特定的,众所周知的顺序(预订,有序,后序等)?

2 个答案:

答案 0 :(得分:17)

排序,是的。 LambdaExpression的实际“主干”(如果您愿意)是.Body;参数是关于树结构(以及它需要的)的必要元数据,但顶部的.Parameters(你的虚线)实际上并不是树的功能图的一部分 - 只有当那些节点是稍后在树的实际主体中使用它们作为值替换。

两次访问的ParameterExpression是必不可少的,因此有人可以根据需要交换参数 - 例如,构建具有相同参数数量的全新LambdaExpression,但是不同的参数实例(可能会更改类型)。

订单相当稳定,但应视为实施细节。例如,给定Add(A,B)之类的节点,我是否应该首先访问A - 第一个与B之间没有语义差异。

答案 1 :(得分:17)

只是为Marc的正确答案添加一点:

  

LINQ表达式树是否指向没有循环的图形?

首先,是的,表达式树是DAG - 有向无环图。

我们知道它们是非循环的,因为表达式树是不可变的,因此必须从叶子构建。在这种情况下,没有办法进行循环,因为 all 循环中的节点必须分配 last ,显然这不会发生。

因为部分是不可变的,所以表达式“tree”实际上不必是树本身。正如Marc指出的那样,您需要重新使用参数的参考;这就是我们如何确定何时使用声明的参数。重新使用其他部分虽然合法,但有些奇怪。例如,如果要表示(int x)=>(x + 1) * (x + 1)主体的表达式树,可以为(x + 1)创建表达式树,然后创建一个乘法节点,其中两个子节点都是表达式树。

  

使用ExpressionVisitor访问LambdaExpression时,将访问ParameterExpression两次。有没有办法使用ExpressionVisitor访问LambdaExpression,以便所有节点只访问一次,并以特定的,众所周知的顺序(预订,有序,后序等)?

ExpressionVisitor是一个抽象类。您可以使用您喜欢的语义制作自己的具体版本。例如,您可以覆盖Visit方法,使其维护已经看到的节点的HashSet,并且不会在先前已接受的节点上调用Accept。