2013-11-07 7 views
3

Я пытаюсь понять этот пример, и я продолжаю терпеть неудачу.Stuck In 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 
    ) 
); 

Я знаю частично, что происходит, но эта метка сбивает с толку меня, так что мои вопросы, что такое ярлык и как, что локальное значение начинают назначается и используется в первом элементе блока?

+0

Вы пробовали глядя на документацию методов в вопросе? – svick

ответ

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) 
}      //) 
+0

Как получить доступ к первому аргументу и установить значение на нем внутри блока? –

+0

Аргумент не открывается первым; сначала он объявляется *, затем инициализируется. Я отредактировал ответ, чтобы уточнить. – Cyanfish

+0

Что значит объявление? Как? –