Search code examples
c#dynamicimplicit-typing

C# Confounding Implicitly typed variable with dynamic


If you run TestClass.Test() you will get a RuntimeBinderException. It all starts with var str = DoSomething(obj); implicitly typing to dynamic rather than string. Can someone explain what is happening here? Why does RequiresString(str); work? I understand that you can't call extension methods on dynamic objects, but this whole thing feels a bit dirty and broken to me. It all compiles fine despite obvious type mismatches then fails at runtime.

public static class ExtensionTest
{
    public static string ToJsonTest(this object x)
    {
        return string.Empty;
    }
}
public static class TestClass
{
    public static void Test()
    {
        dynamic obj = new ExpandoObject();
        obj.var1 = "hello";

        var str = DoSomething(obj);
        var testObj = RequiresString(str);
        var json = testObj.ToJsonTest();
    }
    public static string DoSomething(object x)
    {
        return string.Empty;
    }
    public static TestObj RequiresString(string x)
    {
        return new TestObj();
    }
    public class TestObj
    {
        public int Prop1 { get; set; }
    }
}

Solution

  • The call to RequiresString contains dynamic arguments, so it's resolved at runtime using the actual argument's type. The actual type returned by DoSomething is string, so the runtime binder looks for RequiresString(string), which can be successfully found as TestClass.RequiresString. So far, so good.

    The next call testObj.ToJsonTest() fails, as you already mentioned, because extension methods on dynamic targets are not resolved, so the next call fails.

    Yes, it might feel a little bit dirty because there are (almost) no compile-time checks when dynamics are involved, very much like weakly typed scripting languages. That's why I'd advise using dynamic only if really needed and in the narrowest possible context; in particular, I'd say dynamic should not be seen on class' public surface.