国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

編寫高質量代碼改善C#程序的157個建議——建議15:使用dynamic來簡化反射實現

2019-11-14 14:10:24
字體:
來源:轉載
供稿:網友

建議15: 使用dynamic來簡化反射實現

dynamic是Framework 4.0的新特性。dynamic的出現讓C#具有了弱語言類型的特性。編譯器在編譯的時候不再對類型進行檢查,編譯器默認dynamic對象支持開發者想要的任何特性。比如,即使你對GetDynamicObject方法返回的對象一無所知,也可以像如下這樣進行代碼的調用,編譯器不會報錯:

    dynamic dynamicObject = GetDynamicObject();      Console.WriteLine(dynamicObject.Name);      Console.WriteLine(dynamicObject.SampleMethod()); 

 

當然,如果運行時dynamicObject不包含指定的這些特性(如上文中帶返回值的方法SampleMethod),運行時程序會拋出一個RuntimeBinderException異常:

“System.Dynamic.ExpandoObject”未包含“SampleMethod”的定義。

注意 有人會將var這個關鍵字與dynamic進行比較。實際上,var和dynamic完全是兩個概念,根本不應該放在一起比較。var實際上 是編譯期拋給我們的“語法糖”,一旦被編譯,編譯期會自動匹配var 變量的實際類型,并用實際類型來替換該變量的聲明,這看上去就好像我們在編碼的時候是用實際類型進行聲明的。而dynamic被編譯后,實際是一個 object類型,只不過編譯器會對dynamic類型進行特殊處理,讓它在編譯期間不進行任何的類型檢查,而是將類型檢查放到了運行期。

這從Visual Studio的編輯器窗口就能看出來。以var聲明的變量支持“智能感知”,因為Visual Studio能推斷出var類型的實際類型;而以dynamic聲明的變量卻不支持“智能感知”,因為編譯器對其運行期的類型一無所知。對dynamic 變量使用“智能感知”,會提示“此操作將在運行時解析”。

利用dynamic的這個特性,可以簡化C#中的反射語法。在dynamic出現之前,假設存在類,代碼如下所示:

    public class DynamicSample      {          public string Name { get; set; }               public int Add(int a, int b)          {              return a + b;          }      } 

我們這樣使用反射,調用方代碼如下所示:

    DynamicSample dynamicSample = new DynamicSample();  //為了代碼簡潔簡寫了,沒有寫反射 Assembly.Load(AssemblyPath).CreateInstance(classNamespace),詳細反射代碼見文章結尾,實際開發中是要用反射生成實例的    var addMethod = typeof(DynamicSample).GetMethod("Add");      int re = (int)addMethod.Invoke(dynamicSample, new object[] { 1, 2 }); 

 

在使用dynamic后,代碼看上去更簡潔了,并且在可控的范圍內減少了一次拆箱的機會,代碼如下所示:

    dynamic dynamicSample2 = new DynamicSample(); //為了代碼簡潔簡寫了,沒有寫反射 Assembly.Load(AssemblyPath).CreateInstance(classNamespace),詳細反射代碼見文章結尾,實際開發中是要用反射生成實例的     int re2 = dynamicSample2.Add(1, 2); 

 

我們可能會對這樣的簡化不以為然,畢竟代碼看起來并沒有減少多少,但是,如果考慮到效率兼優美兩個特性,那么dynamic的優勢就顯現出來了。如果對上面的代碼執行1000000次,如下所示:

    int times = 1000000;      DynamicSample reflectSample = new DynamicSample();      var addMethod = typeof(DynamicSample).GetMethod("Add");      Stopwatch watch1 = Stopwatch.StartNew();      for (var i = 0; i < times; i++)      {          addMethod.Invoke(reflectSample, new object[] { 1, 2 });      }      Console.WriteLine(string.Format("反射耗時:{0} 毫秒", watch1.ElapsedMilliseconds));      dynamic dynamicSample = new DynamicSample();      Stopwatch watch2 = Stopwatch.StartNew();      for (int i = 0; i < times; i++)      {          dynamicSample.Add(1, 2);      }      Console.WriteLine(string.Format("dynamic耗時:{0} 毫秒",          watch2.ElapsedMilliseconds)); 

 

輸出為:

反射耗時:2575 毫秒 

dynamic耗時:76 毫秒 

可以看到,沒有優化的反射實現,上面這個循環上的執行效率大大低于dynamic實現的效果。如果對反射實現進行優化,代碼如下所示:

    DynamicSample reflectSampleBetter = new DynamicSample();      var addMethod2 = typeof(DynamicSample).GetMethod("Add");      var delg = (Func<DynamicSample, int, int, int>)Delegate.CreateDelegate(typeof(Func<DynamicSample, int, int, int>), addMethod2);      Stopwatch watch3 = Stopwatch.StartNew();      for (var i = 0; i < times; i++)      {          delg(reflectSampleBetter, 1, 2);      }      Console.WriteLine(string.Format("優化的反射耗時:{0} 毫秒", watch3.ElapsedMilliseconds)); 

 

輸出為:

優化的反射耗時:12 毫秒 

 

可以看到,優化后的反射實現,其效率和dynamic在一個數量級上。可是它帶來了效率,卻犧牲了代碼的整潔度,這種實現在我看來是得不償失的。所以,現在有了dynamic類型,建議大家:

始終使用dynamic來簡化反射實現。

 

轉自:《編寫高質量代碼改善C#程序的157個建議》陸敏技

 

反射代碼:

namespace ReflectionTest{    public class DynamicSample    {        public string Name { get; set; }        public int Add(int a, int b)        {            return a + b;        }    } }
static void Main(string[] args){    string AssemblyPath = "ReflectionTest";//可以通過讀取配置文件來設置值    string classNamespace = "ReflectionTest.DynamicSample";    //原來反射方式    Object dynamicSample = Assembly.Load(AssemblyPath).CreateInstance(classNamespace);    Type type = dynamicSample.GetType();    var addMethod = type.GetMethod("Add");    int re = (int)addMethod.Invoke(dynamicSample, new object[] { 1, 2 });    Console.WriteLine(re);//輸出3    //dynamic反射方式    dynamic dynamicSample2 = Assembly.Load(AssemblyPath).CreateInstance(classNamespace);    int re2 = dynamicSample2.Add(1, 2);//Add為動態表達式,將在運行時解析,這里是沒有智能提示的    Console.WriteLine(re2);//輸出3    Console.Read();}

 


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 永和县| 读书| 沧源| 西贡区| 澄江县| 湄潭县| 德惠市| 兴业县| 长兴县| 大英县| 湖北省| 宁都县| 崇仁县| 庆元县| 信丰县| 鲜城| 黄平县| 明光市| 灵寿县| 迁安市| 高平市| 灵宝市| 涞水县| 阿合奇县| 昔阳县| 城口县| 芜湖县| 宾川县| 宁远县| 鸡泽县| 富平县| 彰化市| 山东省| 修水县| 南丹县| 云浮市| 逊克县| 朝阳县| 瑞丽市| 鄂伦春自治旗| 滦平县|