I’ve been playing around with some C# statements in LINQPad with a view to understanding what intermediate language code is emitted.
I first tried the following code:
var Container = new {Name = "James"};
Console.WriteLine(Container.Name);
And saw the following six lines of IL emitted:
IL_0001: ldstr "James"
IL_0006: newobj <>f__AnonymousType0<System.String>..ctor
IL_000B: stloc.0
IL_000C: ldloc.0
IL_000D: callvirt <>f__AnonymousType0<System.String>.get_Name
IL_0012: call System.Console.WriteLine
Which, is broadly what I expect, and is quite a nice demonstration of how anonymous types are read-only/immutable, seeing as there is no set_Name property.
Next I tried the statements:
dynamic Container = new System.Dynamic.ExpandoObject();
Container.Name = "James";
Console.WriteLine(Container.Name);
Which causes a huge amount of IL to be emitted. I’ll not paste it here, but you can find it in this pastebin.
I understand there is quite a bit of overhead with regard to managing the dynamic type and ExpandoObject, but I don’t understand why it appears that the call to System.Console.WriteLine is in this case performed through internal reflection.
IL_0072: ldstr "WriteLine"
....
IL_00BF: ldtoken System.Console
In the first segment of code, after the property was retrieved and stored, it was a one-line IL statement that invoked System.Console.WriteLine.
So why is all this extra required for the call with a dynamic type?
Because the variable is
dynamicthere is no way to know, at compile time, which overload ofWriteLineshould be called. It’s not until runtime that we know the actual type of thedynamicobject. Because of the waydynamicworks, it’s important that it not just be treated as anobjectat compile time; part of the power is that it is determining the correct overload at runtime.If you cast the object to something other than dynamic (i.e.
stringafter callingToStringor just back toExpandoObject) and then pass it toWriteLinethen you should see that reflection call go away and see it statically determine, at compile time, the proper overload ofWriteLine.