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,這裡是我的開發筆記的網誌,如果你對我的文章有任何疑問或者有錯誤的話,歡迎留言讓我知道。