电竞比分网-中国电竞赛事及体育赛事平台

分享

反射VS委托,到底誰(shuí)更快?

 昵稱(chēng)10504424 2012-09-12

反射VS委托,到底誰(shuí)更快?

       有時(shí)候我們需要?jiǎng)討B(tài)調(diào)用一個(gè)方法,到底用什么方法呢?很多人想到了反射,有的人也想到了委托。大家都知道反射很慢,因?yàn)榉瓷涞念?lèi)型不安全和以尋找字符串的方式來(lái)匹配相對(duì)應(yīng)的成員,所以也有的人用委托,那到底誰(shuí)更快呢?來(lái)看一個(gè)demo:

   

復(fù)制代碼
 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     }
復(fù)制代碼

 假設(shè)正常情況下無(wú)法訪問(wèn)Test中的方法

復(fù)制代碼
  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);
        }
    }
復(fù)制代碼

現(xiàn)在來(lái)測(cè)試一下誰(shuí)更快:

復(fù)制代碼
 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     }
復(fù)制代碼

下面是輸出結(jié)果:

有點(diǎn)意外啊,反射更快,至于是什么原因,大家去討論一下吧,我現(xiàn)在也不是很清楚,有點(diǎn)復(fù)雜啊。。。。。。

當(dāng)然了,還有更好的方法,速度更快,就是使用Dynamic關(guān)鍵字,此關(guān)鍵字在運(yùn)行時(shí)跟object有點(diǎn)類(lèi)似,它創(chuàng)建的對(duì)象只能在運(yùn)行時(shí)去匹配相關(guān)的類(lèi)型成員,所以有點(diǎn)類(lèi)型不安全哦,下面是用dynamic關(guān)鍵字調(diào)用的方法,很簡(jiǎn)單:

  public void InvokeByDynamicKeyword()
        {
            dynamic obj = (Test)Activator.CreateInstance(typeof(Test));
            object result = obj.GetData(10);
        }

同樣執(zhí)行1000*1000次,它需要的時(shí)間如下:

當(dāng)然了,我前面用到了接口,對(duì)于反射速度慢的最佳解決方案是,實(shí)現(xiàn)一個(gè)接口或一個(gè)抽象類(lèi),用他們的引用指向?qū)崿F(xiàn)該接口的成員實(shí)例或繼承該抽象類(lèi)的成員實(shí)例,這是典型的插件編程模式,來(lái)看一下代碼,很簡(jiǎn)單:

 public void InvokeByInterface()
        {
            IGetData obj = (IGetData)Activator.CreateInstance(typeof(Test));
            object result = obj.GetData(10);
        }

同樣執(zhí)行1000*1000次,它需要的時(shí)間如下:

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多