See the question and my original answer on StackOverflow

It happens because the dynamic keyword causes a lot of changes in the generated code structure (generated by the C# compiler).

You can observe this using a tool such as .NET reflector (I suggest to select 'None' for C# inference so you can really see all the generated stuff). Basically, each time you access a dynamic object, the generated code adds at least an if case. These ifs can cause important code paths changes.

For example, this simple C# code

    static void MyFoo(dynamic dyn)
    {
        if (dyn == null)
            return;

        var x = dyn;
    }

is generated as:

private static void MyFoo([Dynamic] object dyn)
{
    object obj2;
    CSharpArgumentInfo[] infoArray;
    bool flag;
    if (<MyFoo>o__SiteContainer0.<>p__Site1 != null)
    {
        goto Label_0038;
    }
    <MyFoo>o__SiteContainer0.<>p__Site1 = CallSite<Func<CallSite, object, bool>>.Create(Binder.UnaryOperation(0, 0x53, typeof(Program), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(0, null) }));
Label_0038:
    if (<MyFoo>o__SiteContainer0.<>p__Site2 != null)
    {
        goto Label_0088;
    }
    <MyFoo>o__SiteContainer0.<>p__Site2 = CallSite<Func<CallSite, object, object, object>>.Create(Binder.BinaryOperation(0, 13, typeof(Program), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(0, null), CSharpArgumentInfo.Create(2, null) }));
Label_0088:
    if ((<MyFoo>o__SiteContainer0.<>p__Site1.Target(<MyFoo>o__SiteContainer0.<>p__Site1, <MyFoo>o__SiteContainer0.<>p__Site2.Target(<MyFoo>o__SiteContainer0.<>p__Site2, dyn, null)) == 0) == null)
    {
        goto Label_00AE;
    }
    obj2 = dyn;
Label_00AE:
    return;
}

Let's take a another simple example. This code:

    static void MyFoo1(dynamic dyn)
    {
        long value;

        if (long.TryParse(dyn, out value))
            return;

        var x = value;
    }

compiles fine. This one

    static void MyFoo2(dynamic dyn)
    {
        long value;

        if (true || long.TryParse(dyn, out value))
            return;

        var x = value;
    }

doesn't. If you look at the generated code (set value to 0 to make sure it compiles), it will simply contain some extra ifs and goto that change the whole code path quite drastically. I don't think it's a bug, maybe more a limitation of the dynamic keyword (that has quite a few, for example: Limitations of the dynamic type in C#)