Не удается передать динамический аргумент и лямбда к методу

Странное поведение DLR. У меня есть метод, который принимает два аргумента: dynamic и Func < > . Когда я пропускаю только динамический ИЛИ только Func < > - нет ошибок. Но когда я пытаюсь передать эти аргументы в одно и то же время - появляется ошибка "Невозможно использовать лямбда-выражение в качестве аргумента для динамически отправленной операции, не введя его прежде всего в тип делегата или дерева выражений".:

    static void Main(string[] args)
    {
        dynamic d = 1;

        Method1(d);// - OK
        Method2(f => 1);// - OK
        Method3(d, f => 1);// - Cannot use a lambda expression as an argument to a dynamically dispatched operation without first casting it to a delegate or expression tree type.
    }

    static void Method1(dynamic d)
    {
    }

    static void Method2(Func<string, int> func)
    {
    }

    static void Method3(dynamic d, Func<string, int> func)
    {
    }

Почему это происходит?

Конечно, я могу сделать явное кастинг, и ошибка исчезнет:

Method3(d, (Func<string, int>)(f => 1));

Но это неудобно. Компилятор знает тип лямбды, почему он требует кастинга?

Ответ 1

Проделали некоторые исследования и прочитали некоторые из ИЛ, сгенерированные компилятором для каждого из ваших случаев.

Это, по-видимому, является ограничением в гибкости динамической компиляции. Поскольку ваш метод принимает динамический параметр, весь вызов теперь становится динамической. Это означает, что все параметры ограничены по времени, поэтому обработка параметров проходит через другой путь обработки во время компиляции, чем для параметров, не участвующих в динамической операции.

Ясно, что, как показывает ваш вызов Method2, компилятор имеет возможность сделать вывод о том, что ваше намерение предназначено для f = > 1 для обработки как Func < string, int > .

Однако, похоже, что эта функциональность, вероятно, из-за сложности построения динамического сайта-звонка, пока не поддерживается в динамической компиляции.

Это один из тех случаев, когда Microsoft еще не поддерживает функцию, но может добавить ее в будущем.

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