Question

J'essaie de comprendre cet exemple et je continue d'échouer.

Ceci est le code:

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

Je sais en partie ce qui se passe, mais cette étiquette me confond donc mes questions sont ce qui est une étiquette et comment cette valeur locale commence-t-elle et utilisée dans le premier élément du bloc?

Était-ce utile?

La solution

Une étiquette identifie une boucle. Je peux comprendre votre confusion, car C # n'a pas réellement d'étiquettes de boucle, mais .NET les utilise en interne et ils sont donc utilisés dans les arbres d'expression de .NET. Voici quelques exemples de code Java (qui a des étiquettes de boucle):

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;
    }
}

La Expression.Loop La méthode prend une étiquette comme un argument, qui dit "cette étiquette fait référence à cette boucle". Lorsque vous avez Expression.Break(label, result), il dit "Sortez de la boucle à laquelle cette étiquette fait référence", qui dans ce cas est la boucle unique du bloc.

Pour la variable locale, Expression.BlockLe premier argument du premier argument déclare toutes les variables locales portée dans ce bloc. Alors result est d'abord déclaré, puis initialisé par le Expression.Assign appel.

L'arbre d'expression résultant est approximativement équivalent à ce code 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)
}                      // )
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top