【问题标题】:Stuck In Expression Trees卡在表达式树中
【发布时间】:2013-11-19 16:27:17
【问题描述】:

我正在努力理解这个例子,但一直失败。

这是代码:

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

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

【问题讨论】:

  • 您是否尝试过查看相关方法的文档?

标签: c# expression-trees


【解决方案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)
}                      // )

【讨论】:

  • 如何访问第一个参数并在块内设置一个值?
  • 参数不先被访问;它首先被声明,然后被初始化。我已经编辑了答案以澄清。
  • 声明是什么意思?怎么样?
  • 我添加了一个代码示例。查看声明“int result;”。
  • 我正在慢慢实现它。如果我将 eac 结果添加到列表并最终返回该列表,那么该块看起来如何?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多