NET4.0新特性 dynamic
以往我們如果有一個dll檔,如果要使用C#來呼叫,我們都會使用反射(Reflection)的方式來呼叫相關的Methods,我先前也有一篇文章有提到關於Reflection的基本操方式。
最近因為因緣巧合的情況之下發現了NET4.0所提供的新特性dynamic,根據MSDN的說法 dynamic 型別可讓它發生所在的作業略過編譯時期型別檢查,講白話文的意思就是dynamic可以讓C#語法有了類似VB的特性弱型別語言的特性,宣告的時候不需要知道型別,且編譯的過程中編譯器預設也不會對dynamic進行檢查。
首先先大概看一下兩者之間的差異。
Reflection的調用方式
dynamic的調用方式
就程式碼看起來好像差異性不大,感覺就是比較輕鬆的呼叫而已,但是如果真的只是比較好呼叫,需要這麼大費周章的再弄一個新特性出來嗎?當然不是,dynamic的新特性大大的提升了呼叫時的效能,下面我就寫一個簡單的例子來看效能上有多大的提升。
我們先寫一個取得呼叫名稱的類別,並將此類別編譯成dll檔,如下所示。
接下來我們就直接跑迴圈100000萬次來看,效能整整差了快10倍。
最近因為因緣巧合的情況之下發現了NET4.0所提供的新特性dynamic,根據MSDN的說法 dynamic 型別可讓它發生所在的作業略過編譯時期型別檢查,講白話文的意思就是dynamic可以讓C#語法有了類似VB的特性弱型別語言的特性,宣告的時候不需要知道型別,且編譯的過程中編譯器預設也不會對dynamic進行檢查。
首先先大概看一下兩者之間的差異。
Reflection的調用方式
Type type = assembly.GetType("BaseMethods.CallMe"); object instance = Activator.CreateInstance(type); type.InvokeMember("GetName", BindingFlags.InvokeMethod, null, instance, new object[] { "Lawrence" });
dynamic的調用方式
Type type = assembly.GetType("BaseMethods.CallMe"); dynamic obj = Activator.CreateInstance(type); obj.GetName("Lawrence");
就程式碼看起來好像差異性不大,感覺就是比較輕鬆的呼叫而已,但是如果真的只是比較好呼叫,需要這麼大費周章的再弄一個新特性出來嗎?當然不是,dynamic的新特性大大的提升了呼叫時的效能,下面我就寫一個簡單的例子來看效能上有多大的提升。
我們先寫一個取得呼叫名稱的類別,並將此類別編譯成dll檔,如下所示。
namespace BaseMethods { public class CallMe { public string GetName(string name) { return string.Format("Hello {0} !", name); } } }
接下來我們就直接跑迴圈100000萬次來看,效能整整差了快10倍。
static void Main(string[] args) { //載入dll Assembly assembly = System.Reflection.Assembly.LoadFile(Application.StartupPath + "\\BaseMethods.dll"); Type type = assembly.GetType("BaseMethods.CallMe"); #region object呼叫方式 object instance = Activator.CreateInstance(type); Console.WriteLine("====透過InvokeMember方式來呼叫===="); string str = type.InvokeMember("GetName", BindingFlags.InvokeMethod, null, instance, new object[] { "Lawrence" } ).ToString(); Console.WriteLine("您呼叫的是有參數的方法,回傳值 : " + str); Console.WriteLine(""); #endregion #region dynamic呼叫方式 Console.WriteLine("====透過Dynamic方式來呼叫===="); dynamic obj = Activator.CreateInstance(type); string str1 = obj.GetName("Lawrence"); Console.WriteLine("您呼叫的是有參數的方法,回傳值 : " + str1); Console.WriteLine(""); #endregion Stopwatch sw = new Stopwatch(); #region object呼叫方式迴圈 Console.WriteLine("====透過InvokeMember 迴圈呼叫100000次的時間===="); sw.Start(); for (int i = 0; i < 100000; i++) { type.InvokeMember("GetName", BindingFlags.InvokeMethod, null, instance, new object[] { "Lawrence" } ).ToString(); } sw.Stop(); Console.WriteLine("InvokeMember所花費時間 {0}ms", sw.ElapsedMilliseconds); Console.WriteLine(""); sw.Reset(); #endregion #region dynamic呼叫方式迴圈 Console.WriteLine("====透過Dynamic 迴圈呼叫100000次的時間===="); sw.Start(); for (int i = 0; i < 100000; i++) { obj.GetName("Lawrence"); } sw.Stop(); Console.WriteLine("Dynamic所花費時間 {0}ms", sw.ElapsedMilliseconds); Console.WriteLine(""); sw.Reset(); #endregion Console.Read(); }
本文範例 :
Dynamic.zip
Dynamic.zip
留言
張貼留言
您好,我是 Lawrence,這裡是我的開發筆記的網誌,如果你對我的文章有任何疑問或者有錯誤的話,歡迎留言讓我知道。