Search code examples
c#.netdynamic-language-runtime

Why do I have to cast results from dynamic coming into typed parameters


I have a simple dynamic object that returns a double:

class MyDynamic : DynamicObject
{
    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        result = 2.0;
        return true;
    }
}

Then, I try to call a method that takes an int:

    private static void SomeMethod(int number)
    {

    }

Then, I make a call and pass my value from the dynamic into the method:

        dynamic x = new MyDynamic();
        SomeMethod(x.number);

Now, this causes an exception because the runtime complains it can't find a relevant method. Is that the expected behavior? I would have expected the runtime to automatically cast the returned value to whatever the type requested by the method is (int, in this instance).

Is this how stuff is supposed to work?


Solution

  • I would have expected the runtime to automatically cast the returned value to whatever the type requested by the method is (int, in this instance).

    Why would you expect it to do that? There's no implicit conversion from double to int normally, so why would you expect it in a dynamically-typed context?

    To put it another way - if x.number were statically typed to return double, you'd get a compile-time failure. The execution-time failure when using dynamic typing is mirroring the same failure. Basically, the attempt to find the right method to call is being deferred until execution time, when the type of the argument is known. The type of the argument turns out to be double, and there's no implicit conversion from double to int, so you're getting an exception.

    If you try it the other way round - supplying an int in TryGetMember and then calling a method accepting double - then the implicit conversion should kick in.

    Note that you can use the explicit conversion from double to int with a cast:

    SomeMethod((int) x.number);
    

    That forces overload resolution at compile-time, and just the conversion of x.number to int at execution time... which is fine here because the explicit conversion from double to int exists.

    Note that you don't have to use a method to demonstrate this:

    int y = x.number; // Fails at execution time
    int z = (int) x.number; // Works
    

    Basically, the conversion from double to int is explicit, and that requirement for you to be explicit is upheld in dynamic typing too.