Frage

Ich versuche dieses Beispiel zu verstehen und versage immer wieder.

Dies ist der 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
    )
);

Ich weiß teilweise, was los ist, aber dieses Etikett verwirrt mich. Meine Fragen sind also, was ein Etikett ist und wie wird dieser lokale Wert im ersten Element des Blocks zugewiesen und verwendet?

War es hilfreich?

Lösung

Ein Etikett identifiziert eine Schleife. Ich kann Ihre Verwirrung verstehen, da C# eigentlich keine Schleifenbezeichnungen enthält, aber .NET sie intern verwendet und sie werden daher in .NETs Ausdrucksbäumen verwendet. Hier ist ein Beispiel für Java -Code (der Schleifenbezeichnungen enthält):

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

Das Expression.Loop Die Methode nimmt ein Etikett als Argument an, das besagt, dass "dieses Etikett sich auf diese Schleife bezieht". Wenn du. .. hast Expression.Break(label, result), Es heißt "Brechen Sie aus der Schleife aus, auf die sich dieses Etikett bezieht", was in diesem Fall die einzelnen Schleife des Blocks ist.

Für die lokale Variable, Expression.BlockDas erste Argument erklärt alle lokalen Variablen, die zu diesem Block geschrieben sind. So result wird zuerst deklariert und dann von der initialisiert Expression.Assign Anruf.

Der resultierende Ausdrucksbaum entspricht ungefähr diesem C# -Code:

{                      // 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)
}                      // )
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top