3

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

这是代码:

// 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
    )
);

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

4

1 回答 1

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)
}                      // )
于 2013-11-07T21:47:27.900 回答