zoukankan      html  css  js  c++  java
  • 使用dynamic来简化反射实现

           dynamic是Framework4.0的新特性。dynamic的出现让C#具有弱语言类型特性。编译器在编译的时候不再对类型进行检查,编译器默认dynamic对象支持开发者想要的任何特性。

          比如,即使你对GetDynamicObject方法返回的对象一无所知,也可以像如下这样进行代码的调用,编译器不会报错。

         

    1 dynamic dynamicObject=GetDynamicObject();
    2 Console.WriteLine(dynamicObject.Name);
    3 Console.WriteLine(dynamicObject.SampleMethod());
    View Code

    当然,如果运行时dynamicObject不包含指定的这些特性(如上文中带返回值的方法SampleMethod),运行时程序会抛出一个RuntimeBinderException异常:
    “System.Dynamic.ExpandoObject”未包含“SampleMethod”的定义。

    利用dynamic的这个特性,可以简化C#中的反射语法。在dynamic出现之前,假设存在类,代码如下所示:

    1 public class DynamicSample
    2 {
    3   public string Name{get;set;}
    4  public int Add(int a,int b)
    5  {
    6   return a+b;
    7  }
    8 }
    View Code

    我们这样使用反射,调用如下方法:

    1 DynamicSample dynamicSample=new DynamicSample();
    2 var addMethod=typeof(DynamicSample).GetMethod("Add");
    3 int result=(int)addMethod.Invoke(dynamicSample,new object[]{1,2});

    在使用dynamic后,代码看上去更简洁了,并且在可控的范围内减少了异常拆箱的机会,代码如下所示:

     1 DynamicSample dynamicSample2=new DynamicSample();

     2 int result2=dynamicDample.Add(1,2); 

    我们可能会对这样的简化不以为然,毕竟代码看起来并没有减少多少,但是,如果考虑到效率兼优美两个特性,那么dynamic的优势就凸显出来了。如果对上面的代码执行1000000次,如下代码:

     1             int times = 1000000;
     2             DynamicSample refSample = new DynamicSample();
     3             var addMethod = typeof(DynamicSample).GetMethod("Add");
     4             Stopwatch sw = Stopwatch.StartNew();
     5             for (int i = 0; i < times; i++)
     6             {
     7                 addMethod.Invoke(refSample, new object[] { 1, 2 });
     8             }
     9             Console.WriteLine(string.Format("反射耗时:{0}毫秒",sw.ElapsedMilliseconds));
    10             dynamic dynamicSample = new DynamicSample();
    11             Stopwatch sw2 = Stopwatch.StartNew();
    12             for (int i = 0; i < times; i++)
    13             {
    14                 dynamicSample.Add(1, 2);
    15             }
    16             Console.WriteLine(string.Format("dynamic耗时:{0}毫秒",sw2.ElapsedMilliseconds));
    View Code

    输出结果分别为(每次执行结果都不一样,但比例均匀):
    反射耗时:1107毫秒
    dynamic耗时:209毫秒

    可以看到,没有优化的反射实现,上面这个循环上的执行效率大大低于dynamic实现的效果。如果对反射实现进行优化,代码如下所示:

     1            //优化后的反射实现
     2             DynamicSample refSampleBetter = new DynamicSample();
     3             var addMethod2 = typeof(DynamicSample).GetMethod("Add");
     4             var delg = (Func<DynamicSample, int, int, int>)Delegate.CreateDelegate(typeof(Func<DynamicSample, int, int, int>), addMethod2);
     5             Stopwatch sw3 = Stopwatch.StartNew();
     6             for (int i = 0; i < times; i++)
     7             {
     8                 delg(refSampleBetter, 1, 2);
     9             }
    10             Console.WriteLine(string.Format("优化的反射耗时:{0}毫秒",sw3.ElapsedMilliseconds));
    View Code

    输出结果为:
    优化的反射耗时:36毫秒
    可以看到,优化后的反射实现,期效率和dynamic在一个数量级上。可是它带来的效率,却牺牲了代码的整洁度,这种实现在我看来是得不偿失的。所以,现在有了dynamic类型,

    建议大家:始终使用dynamic来简化反射实现。

  • 相关阅读:
    vue 路由
    CSS篇-dispaly、position、定位机制、布局、盒子模型、BFC
    CSS篇-样式表、选择器、权重、伪类
    vue-cli3.0 开发环境构建
    Vue 全家桶学习资源(转)
    vue全家桶常用命名
    服务拆分
    分布式事务及其解决方法
    java mvc 及其缓存
    java 面试经典题
  • 原文地址:https://www.cnblogs.com/xiaowu54/p/10649570.html
Copyright © 2011-2022 走看看