Как создать Выражение <Func <динамичный, динамичный>> - Или действительно ли это - ошибка?

Во время моей работы с деревьями выражений в течение нескольких дней теперь, я столкнулся с чем-то, что я нахожу трудными понять; надо надеяться, кто-то сможет так проливает некоторый свет здесь.

Если Вы кодируете Expression<Func<dynamic, dynamic>> expr1 = x => 2 * x; компилятор будет жаловаться, и Вы не доберетесь нигде. Однако кажется, что при создании одного такого выражения через метод затем, компилятор, кажется, доволен этим и получающиеся работы приложения. Это не имеет смысла, таким образом, я задаюсь вопросом, что продолжается позади занавесок.

Я предполагаю что, под капотом, выражение, возвращенное ConvertExpression возможно, имеет тип Expression<Func<object, object>>, который является допустимым типом, но он озадачивает меня, что я не могу использовать Expression<Func<dynamic, dynamic>> введите в объявлении, и все же я могу использовать его в качестве типа возврата метода. Посмотрите пример ниже.

Большое спасибо!

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;
    }
}
9
задан svick 17 June 2013 в 16:53
поделиться

2 ответа

Я полагаю, что под капотом выражение, возвращаемое преобразованием, является, возможно, типа выражения > , который является действительным типом

Правильный.

Я не могу использовать Expression > введите декларацию, и все же я могу использовать его в качестве обратного типа метода.

Эта часть утверждения неверна. Как вы заметите в своем примере, совершенно законно использовать этот тип в декларации локальной переменной.

Чем не является законным, является выполнение динамической операции внутри лямбда, которая преобразуется в тип дерева выражения. Конкретный тип дерева выражения не имеет значения; Что дело в том, что операция динамически.

13
ответ дан 4 December 2019 в 13:01
поделиться

Ошибка компилятора Я получил, когда я попробовал, был «Ошибка CS1963: дерево выражения может не содержать динамическую операцию». Я изменил проблему строки на выражение > expr1 = x => x; (удаление «операции» из лямбда) и работало! Таким образом, вам разрешено иметь динамику в выражениях, но вы не можете на самом деле выполнять какие-либо «операции» на них. Не очень полезно, я знаю. В моем тестировании даже .ToString () считается как операция.

3
ответ дан 4 December 2019 в 13:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: