Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can not pass dynamic argument and lambda to the method

Tags:

c#

dynamic

lambda

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?

like image 704
Storm34 Avatar asked Jun 27 '15 14:06

Storm34


People also ask

Can we use dynamic in lambda expression?

In 2010, the Dynamic Type was introduced and that gave us the ability to create dynamic lambda expressions.

Can we write a Parameterless lambda expression?

No, there isn't. Lambda expressions are optimised (in terms of syntax) for the single parameter case. I know that the C# team feels your pain, and have tried to find an alternative. Whether there ever will be one or not is a different matter.


1 Answers

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.

like image 120
Ayo I Avatar answered Sep 30 '22 00:09

Ayo I