被困在表达树中

时间:2013-11-07 20:21:29

标签: c# expression-trees

我试图理解这个例子,但我一直都在失败。

这是代码:

// Creating a parameter expression.
ParameterExpression value = Expression.Parameter(typeof(int), "value");

// Creating an expression to hold a local variable. 
ParameterExpression result = Expression.Parameter(typeof(int), "result");

// Creating a label to jump to from a loop.
LabelTarget label = Expression.Label(typeof(int));

// Creating a method body.
BlockExpression block = Expression.Block(
    // Adding a local variable. 
    new[] { result },
    // Assigning a constant to a local variable: result = 1
    Expression.Assign(result, Expression.Constant(1)),
    // Adding a loop.
        Expression.Loop(
    // Adding a conditional block into the loop.
           Expression.IfThenElse(
    // Condition: value > 1
               Expression.GreaterThan(value, Expression.Constant(1)),
    // If true: result *= value --
               Expression.MultiplyAssign(result,
                   Expression.PostDecrementAssign(value)),
    // If false, exit the loop and go to the label.
               Expression.Break(label, result)
           ),
    // Label to jump to.
       label
    )
);

我部分地知道发生了什么,但是这个标签让我感到困惑,所以我的问题是什么是标签以及如何在块的第一项中开始分配和使用本地值?

1 个答案:

答案 0 :(得分:1)

标签标识循环。我可以理解你的困惑,因为C#实际上没有循环标签,但.NET确实在内部使用它们,因此它们被用在.NET的表达式树中。这里有一些示例Java代码(它有循环标签):

outerLoop: // This is a label for the outer loop
while (true) {
    innerLoop: // This is a label for the inner loop
    while (true) {
        // Rather than exiting the inner loop (which is what a plain break would
        // do), this exits the outer loop
        break outerLoop;
    }
}

Expression.Loop方法将标签作为参数,表示"此标签引用此循环"。当你有Expression.Break(label, result)时,它会说"突破这个标签引用的循环",在这种情况下是块的单循环。

对于局部变量,Expression.Block的第一个参数声明了作用于该块的所有局部变量。因此首先声明result,然后通过Expression.Assign调用初始化。

生成的表达式树大致相当于此C#代码:

{                      // Expression.Block(
    int result;        //   new[] { result },
    result = 1;        //   Expression.Assign(result, Expression.Constant(1)),
    while (true)       //   Expression.Loop(
    {                  
        if (value > 1) //     Expression.IfThenElse(
        {              //       Expression.GreaterThan(value, Expression.Constant(1)),
            result *=  //       Expression.MultiplyAssign(result,
              value--; //       Expression.PostDecrementAssign(value)),
        }
        else             
        {
            break;     //       Expression.Break(label, result)
        }              //     ),
    }                  //   label)
}                      // )
相关问题