反射VS委托,到底誰更快?有時候我們需要動態(tài)調(diào)用一個方法,到底用什么方法呢?很多人想到了反射,有的人也想到了委托。大家都知道反射很慢,因?yàn)榉瓷涞念愋筒话踩鸵詫ふ易址姆绞絹砥ヅ湎鄬?yīng)的成員,所以也有的人用委托,那到底誰更快呢?來看一個demo:
1 public interface IGetData 2 { 3 int GetData(int data); 4 } 5 6 public class Test : IGetData 7 { 8 public int GetData(int data) 9 { 10 return data; 11 } 12 } 假設(shè)正常情況下無法訪問Test中的方法 public class InvokeTestMember { private const BindingFlags flag = BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public; /// <summary> /// 使用反射 /// </summary> public void InvokeByReflect() { Test obj = (Test)Activator.CreateInstance(typeof(Test)); MethodInfo mi = typeof(Test).GetMethod("GetData", flag); object result = mi.Invoke(obj, new object[] { 10 }); } /// <summary> /// 使用委托 /// </summary> public void InvokeByCreateDelegate() { Test obj = (Test)Activator.CreateInstance(typeof(Test)); MethodInfo mi = typeof(Test).GetMethod("GetData", flag); Func<int, int> del = (Func<int, int>)Delegate.CreateDelegate(typeof(Func<int, int>), obj, mi); object result = del(10); } } 現(xiàn)在來測試一下誰更快: 1 class Program 2 { 3 static void Main(string[] args) 4 { 5 Go(); 6 } 7 8 static void Go() 9 { 10 InvokeTestMember itm = new InvokeTestMember(); 11 12 Stopwatch sw = Stopwatch.StartNew(); 13 for (int i = 0; i < 1000 * 1000; i++) 14 { 15 itm.InvokeByCreateDelegate(); 16 } 17 Console.WriteLine("invokebydelegate: " + sw.Elapsed); 18 19 sw = Stopwatch.StartNew(); 20 for (int i = 0; i < 1000 * 1000; i++) 21 { 22 itm.InvokeByReflect(); 23 } 24 Console.WriteLine("invokebyreflect: " + sw.Elapsed); 25 } 26 } 下面是輸出結(jié)果:
有點(diǎn)意外啊,反射更快,至于是什么原因,大家去討論一下吧,我現(xiàn)在也不是很清楚,有點(diǎn)復(fù)雜啊。。。。。。 當(dāng)然了,還有更好的方法,速度更快,就是使用Dynamic關(guān)鍵字,此關(guān)鍵字在運(yùn)行時跟object有點(diǎn)類似,它創(chuàng)建的對象只能在運(yùn)行時去匹配相關(guān)的類型成員,所以有點(diǎn)類型不安全哦,下面是用dynamic關(guān)鍵字調(diào)用的方法,很簡單: public void InvokeByDynamicKeyword() { dynamic obj = (Test)Activator.CreateInstance(typeof(Test)); object result = obj.GetData(10); } 同樣執(zhí)行1000*1000次,它需要的時間如下:
當(dāng)然了,我前面用到了接口,對于反射速度慢的最佳解決方案是,實(shí)現(xiàn)一個接口或一個抽象類,用他們的引用指向?qū)崿F(xiàn)該接口的成員實(shí)例或繼承該抽象類的成員實(shí)例,這是典型的插件編程模式,來看一下代碼,很簡單: public void InvokeByInterface() { IGetData obj = (IGetData)Activator.CreateInstance(typeof(Test)); object result = obj.GetData(10); } 同樣執(zhí)行1000*1000次,它需要的時間如下: |
|
|
來自: 昵稱10504424 > 《C#》