Wie erstelle ich einen Ausdruck? <Func<dynamic, dynamic> &gt; - Oder ist es ein Fehler?

.net-4.0 c# dynamic expression-trees lambda

Frage

Während meiner Arbeit mit Ausdrucksbäumen für einige Tage stieß ich auf etwas, das ich schwierig zu verstehen bin; Hoffentlich kann hier jemand etwas Licht spenden.

Wenn Sie den Code Expression<Func<dynamic, dynamic>> expr1 = x => 2 * x; Der Compiler wird sich beschweren und Sie werden nirgendwohin kommen. Wenn Sie jedoch einen solchen Ausdruck mit einer Methode erstellen, scheint der Compiler sich darüber zu freuen und die resultierende App funktioniert. Das macht keinen Sinn, also frage ich mich, was hinter den Vorhängen passiert.

Ich nehme an, dass der von ConvertExpression Ausdruck vielleicht vom Typ Expression<Func<object, object>> , was ein gültiger Typ ist, aber es Expression<Func<dynamic, dynamic>> mich, dass ich Expression<Func<dynamic, dynamic>> nicht verwenden kann Expression<Func<dynamic, dynamic>> gebe eine Deklaration ein und kann sie trotzdem als Rückgabetyp einer Methode verwenden. Siehe ein Beispiel unten.

Danke vielmals!

public class ExpressionExample
{
    public void Main()
    {
        // Doesn't compile:
        //Expression<Func<dynamic, dynamic>> expr1 = x => 2 * x;

        // Compiles and works - OK
        Expression<Func<double, double>> expr2 = x => 2 * x;
        Func<double, double> func2 = (Func<double, double>)expr2.Compile();
        Console.WriteLine(func2(5.0).ToString()); // Outputs 10

        // Compiles and works - ??? This is the confusing block...
        Expression<Func<dynamic, dynamic>> expr3 = ConvertExpression(expr2);
        Func<dynamic, dynamic> func3 = (Func<dynamic, dynamic>)expr3.Compile();
        Console.WriteLine(func3(5.0).ToString()); // Outputs 10

        // Side note: compiles and works:
        Expression<Func<object, object>> expr4 = x => double.Parse(2.ToString()) * double.Parse(x.ToString());
        Func<object, object> func4 = (Func<object, object>)expr4.Compile();
        Console.WriteLine(func4(5.0).ToString()); // Outputs 10
    }

    private Expression<Func<dynamic, dynamic>> ConvertExpression<TInput, TOutput>(Expression<Func<TInput, TOutput>> expression)
    {
        Expression<Func<object, TInput>> convertToInput = value => (TInput)value;
        // The following doesn't compile: var input = Expression.Parameter(typeof(dynamic), "input");

        var input = Expression.Parameter(typeof(object), "input");        

        Expression<Func<TOutput, dynamic>> convertToOutput = value => (dynamic)value;

        var body = Expression.Invoke(convertToOutput, Expression.Invoke(expression, Expression.Invoke(convertToInput, input)));
        var lambda = Expression.Lambda<Func<dynamic, dynamic>>(body, input);

        return lambda;
    }
}

Akzeptierte Antwort

Ich nehme an, dass der von ConvertExpression zurückgegebene Ausdruck möglicherweise vom Typ Expression<Func<object, object>> , das ein gültiger Typ ist

Richtig.

Ich kann Expression<Func<dynamic, dynamic>> in einer Deklaration nicht verwenden und kann sie dennoch als Rückgabetyp einer Methode verwenden.

Dieser Teil der Aussage ist falsch. Wie Sie in Ihrem Beispiel bemerken, ist es vollkommen legal, diesen Typ in der Deklaration einer lokalen Variablen zu verwenden.

Das Bit, das nicht zulässig ist, ist die Ausführung einer dynamischen Operation in einem Lambda, das in einen Ausdrucksbaumtyp konvertiert wird. Der spezifische Ausdrucksbaumtyp ist irrelevant; Wichtig ist, dass die Operation dynamisch ist.


Beliebte Antwort

Der Compilerfehler, den ich bekam, als ich Ihren Code ausprobierte, war "Fehler CS1963: Ein Ausdrucksbaum darf keine dynamische Operation enthalten". Ich habe die Problemlinie in Expression<Func<dynamic, dynamic>> expr1 = x => x; (Entfernen der "Operation" aus dem Lambda) und es hat funktioniert! Sie dürfen Dynamiken in Ausdrücken haben, aber Sie können keine "Operationen" auf ihnen ausführen. Nicht sehr hilfreich, ich weiß. In meinen Tests zählt sogar .ToString() als Operation.




Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum