14

Strange behavior of DLR. I have a method accepts two arguments: dynamic and Func<>. When I pass only dynamic OR only Func<> - no errors. But when I try to pass these arguments at same time - appears error "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 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)
    {
    }

Why it happens?

Of course I can make explicit casting, and error go away:

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

But it is uncomfortably. The compiler knows type of lambda, why it requires casting?

Storm34
  • 143
  • 6
  • It's not an answer, but a small research about this topic http://weblogs.asp.net/davidfowler/dynamic-linq-a-little-more-dynamic – Anton Sizikov Jun 27 '15 at 14:23
  • possible duplicate of [C# - Passing an anonymous function as a parameter](http://stackoverflow.com/questions/10899761/c-sharp-passing-an-anonymous-function-as-a-parameter) – Anton Sizikov Jun 27 '15 at 14:26
  • if its uncomfortably You can type `Method3((int) d, f => 1);`. and it works. i deleted my answer because i got confused too! about what you said. but ill let you know if i find what is really happening. how ever you should know type of `f => 1` is not known until its specified by you or method parameters. – M.kazem Akhgary Jun 28 '15 at 14:08

1 Answers1

6

Have done some research and read through some of the IL generated by the compiler for each of your cases.

This seems to be a limitation in the flexibility of dynamic compilation. Because your method takes a dynamic parameter, the entire call, now becomes a dynamic operation. This means that all of the parameters are late bound, so the processing of the parameters goes through a different processing path during compilation than for parameters not participating in a dynamic operation.

Clearly, as your call to Method2 demonstrates, the compiler has the ability to infer that your intent is for f => 1 to be treated as a Func<string,int>.

However, it looks like this functionality, probably because of the complexity of building out the dynamic call-site, is not yet supported in dynamic compilation.

This is one of those cases where Microsoft is not yet supporting a feature, but may add it in the future.

For now it looks like you have no choice but to give the compiler a hint.

Ayo I
  • 7,722
  • 5
  • 30
  • 40