文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>我也来说说Dynamic

我也来说说Dynamic

时间:2010-12-14  来源:愚溪

 


1.Dynamic关键字是为了方便访问某个对象。而跟DLR没太大关系。

使用了dynamic关键字创建的对象实际上是一个object. 使用.net 4.0以下的Reflector就可以看到.

使用dynamic关键字后编译器将会将这个对象后面的PropertyName翻译成相应Binder调用。因此语法检查器会忽略检查此对象是否包含PropertyName.

真正的跟DLR有关的是在System.Dynamic下的类型。

大家可以实验一个叫ExpandoObject的东西

这个时候用dynamic是不是有点动态语言的感觉了?所以说 dynamic不是DLR的实现,
但要用DLR在C#里最好的途径可能就是使用dynimic了。
2.Dynamic关键字是一个编译器做的语法糖

 

private static void Main(string[] args)
{
 dynamic expandoObject = new ExpandoObject();
 expandoObject.PropertyA = "PropertyA";
 expandoObject.PropertyB = 2010;
 Console.WriteLine(expandoObject.PropertyA);
 Console.WriteLine(expandoObject.PropertyB);
}

 

 

请看如下代码:

原始代码

public class Program
 {
 static void Main(string[] args)
 {

 Method1();
 Method2();
 Method3();
 Method4();
 }
 private static void Method1()
 {
 dynamic d = new TestClass();
 d.TestProperty = "";
 }
 private static void Method2()
 {
 TestClass t = new TestClass();
 dynamic d1 = t;
 dynamic d2 = t;
 d1.TestProperty = "";
 d2.TestProperty = "";

 }
 private static void Method3()
 {
 dynamic d = new TestClass();
 for (int i = 0; i < 100; i++)
 {
 d.TestProperty = i.ToString();

 }
 }
 private static void Method4()
 {

 for (int i = 0; i < 100; i++)
 {
 dynamic d = new TestClass();
 d.TestProperty = i.ToString();

 }
 }
 }

 class TestClass
 {
 public string TestProperty { get; set; }
 }




用3.5语法反编译的
其实上面也都说的很清楚了 编译器会把dynamic编译在一个和dynamic所在函数名有关的Static SiteContainer

<Method1>o__SiteContainer0
<Method2>o__SiteContainer2 …等

 

而且是一个dynamic生成一个Site .装在对应的Container中。

下面我们来看Method1 反编译后

private static void Method1()
{
 object d = new TestClass();
 if (<Method1>o__SiteContainer0.<>p__Site1 == null)
 {
 <Method1>o__SiteContainer0.<>p__Site1 = 
CallSite<Func<CallSite, object, string, object>>.Create(
Binder.SetMember(CSharpBinderFlags.None, "TestProperty", 
typeof(Program), new CSharpArgumentInfo[] { 
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), 
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.Constant 
| CSharpArgumentInfoFlags.UseCompileTimeType, null) }));
 }
 <Method1>o__SiteContainer0.<>p__Site1.Target(<Method1>o__SiteContainer0.<>p__Site1, d, "");
}

可以看出d其实是个Object了访问属性通过Site实现,而且这里的Site判空,意味着可以缓存。

Method2反编译后

private static void Method2()
{
 TestClass t = new TestClass();
 object d1 = t;
 object d2 = t;
 if (<Method2>o__SiteContainer2.<>p__Site3 == null)
 {
 <Method2>o__SiteContainer2.<>p__Site3 = 
CallSite<Func<CallSite, object, string, object>>.Create(
Binder.SetMember(CSharpBinderFlags.None, "TestProperty", typeof(Program), new CSharpArgumentInfo[] 
{ CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), 
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) }));
 }
 <Method2>o__SiteContainer2.<>p__Site3.Target(<Method2>o__SiteContainer2.<>p__Site3, d1, "");
 if (<Method2>o__SiteContainer2.<>p__Site4 == null)
 {
 <Method2>o__SiteContainer2.<>p__Site4 = 
CallSite<Func<CallSite, object, string, object>>.Create(
Binder.SetMember(CSharpBinderFlags.None, "TestProperty", typeof(Program), 
new CSharpArgumentInfo[] {
 CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), 
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) }));
 }
 <Method2>o__SiteContainer2.<>p__Site4.Target(<Method2>o__SiteContainer2.<>p__Site4, d2, "");
}

 

 


虽然 d1 d2 都指向了 同一个对象t.但这里还是创建了两个Site。可见出现了多少个dynamic就会创建多少个site.

再看Method3和Method4

private static void Method3()
{
 object d = new TestClass();
 for (int i = 0; i < 100; i++)
 {
 if (<Method3>o__SiteContainer5.<>p__Site6 == null)
 {
 <Method3>o__SiteContainer5.<>p__Site6 = 
CallSite<Func<CallSite, object, string, object>>.Create(
Binder.SetMember(CSharpBinderFlags.None, "TestProperty", 
typeof(Program), new CSharpArgumentInfo[] 
{ CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), 
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType, null) }));
 }
 <Method3>o__SiteContainer5.<>p__Site6.Target(<Method3>o__SiteContainer5.<>p__Site6, d, i.ToString());
 }
}
private static void Method4()
{
 for (int i = 0; i < 100; i++)
 {
 object d = new TestClass();
 if (<Method4>o__SiteContainer7.<>p__Site8 == null)
 {
 <Method4>o__SiteContainer7.<>p__Site8 = C
allSite<Func<CallSite, object, string, object>>.Create(
Binder.SetMember(CSharpBinderFlags.None, "TestProperty", 
typeof(Program), new CSharpArgumentInfo[] 
{ CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), 
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType, null) }));
 }
 <Method4>o__SiteContainer7.<>p__Site8.Target(<Method4>o__SiteContainer7.<>p__Site8, d, i.ToString());
 }
}


可见dynamic写在循环里和循环外都是一样的。因为编译器只看到一个dynamic。只生成了一个site.由于site一样且经过缓存,
可以猜想性能不会相差太。
3.Dynamic做了会做缓存,加速访问

由于Site和SiteContainer都是Staic的,所以凡是重复对一个dynamic操作多次都会受益于这种cache。眼看要下班了。笔先收一下,有时间再写:-)

 

相关阅读 更多 +
排行榜 更多 +
辰域智控app

辰域智控app

系统工具 下载
网医联盟app

网医联盟app

运动健身 下载
汇丰汇选App

汇丰汇选App

金融理财 下载