Unexpected compile time error with dynamic
See the question and my original answer on StackOverflowIt 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#)