我一直在使用LINQPad中的一些 C# 语句,以了解发出了什么中间语言代码。
我首先尝试了以下代码:
var Container = new {Name = "James"};
Console.WriteLine(Container.Name);
并看到以下六行 IL 发出:
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
这大致是我所期望的,并且很好地展示了匿名类型如何是只读/不可变的,因为没有 set_Name 属性。
接下来我尝试了以下语句:
dynamic Container = new System.Dynamic.ExpandoObject();
Container.Name = "James";
Console.WriteLine(Container.Name);
这会导致大量的 IL 被排放。我不会在这里粘贴它,但你可以在这个 pastebin中找到它。
我知道在管理动态类型和 ExpandoObject 方面有相当多的开销,但我不明白为什么在这种情况下调用似乎System.Console.WriteLine
是通过内部反射执行的。
IL_0072: ldstr "WriteLine"
....
IL_00BF: ldtoken System.Console
在第一段代码中,在检索和存储属性之后,它是一个单行 IL 语句,它调用了System.Console.WriteLine
.
那么为什么使用dynamic
类型的调用需要所有这些额外的东西呢?