• <label id="pxtpz"><meter id="pxtpz"></meter></label>
      1. <span id="pxtpz"><optgroup id="pxtpz"></optgroup></span>

        當前位置:雨林木風下載站 > 技術開發教程 > 詳細頁面

        .NET Delegates: A C# Bedtime Story中文版(上篇)轉

        .NET Delegates: A C# Bedtime Story中文版(上篇)轉

        更新時間:2022-05-13 文章作者:未知 信息來源:網絡 閱讀次數:

        作者:Chris Sells
        譯者:榮耀
        【譯注:C#進階文章。Chris Sells是《ATL Internals》一書作者之一。譯文中所有程
        序調試環境均為Microsoft Visual Studio.NET 7.0 Beta2和 Microsoft .NET Framewo
        rk SDK Beta2。代碼就是文章,請仔細閱讀代碼J】
        類型耦合
        從前,在南方的一個異國他鄉,有一個叫peter的勤勞的工人。他對boss百依百順,但他
        的boss卻是個卑鄙無信的小人,他堅持要求peter不斷匯報工作情況。由于peter不希望
        被boss盯著干活,于是他向boss承諾隨時匯報工作進度。peter利用類型引用定期回調b
        oss來實現這個承諾:
        using System;//【譯注:譯者補充】
        class Worker
        {
         public void Advise(Boss boss)
        {
        _boss = boss;
        }
         public void DoWork()
         {
        Console.WriteLine("Worker: work started");
        if( _boss != null ) _boss.WorkStarted();
        Console.WriteLine("Worker: work progressing");
        if( _boss != null ) _boss.WorkProgressing();
        Console.WriteLine("Worker: work completed");
        if( _boss != null )
         {
        int grade = _boss.WorkCompleted();
        Console.WriteLine("Worker grade = " + grade);
         }
         }
         private Boss _boss;
        }
        class Boss
        {
         public void WorkStarted() { /*boss不關心. */ }
         public void WorkProgressing() { /*boss不關心. */ }
         public int WorkCompleted()
         {
        Console.WriteLine("It's about time!");
         return 2; /* out of 10 */
         }
        }
        class Universe
        {
         static void Main()
         {
         Worker peter = new Worker();
         Boss boss = new Boss();
        peter.Advise(boss);
        peter.DoWork();
        Console.WriteLine("Main: worker completed work");
        Console.ReadLine();
         }
        }
        /*【譯注:以下是上段程序輸出結果:
        Worker: work started
        Worker: work progressing
        Worker: work completed
        It's about time!
        Worker grade = 2
        Main: worker completed work
        】*/
        接口
         現在,peter成了一個特殊人物,他不但能夠忍受卑鄙的boss,和universe也建立
        了緊密的聯系。peter感到universe對他的工作進程同樣感興趣。不幸的是,除了保證b
        oss能夠被通知外,如果不為universe添加一個特殊的通知方法和回調,peter無法向un
        iverse通知其工作進程。Peter希望能從那些通知方法的實現中分離出潛在的通知約定,
        為此,他決定將方法剝離到接口中:
        using System; //【譯注:譯者補充】
        interface IWorkerEvents //【譯注:這就是分離出來的接口】
        {
         void WorkStarted();
         void WorkProgressing();
         int WorkCompleted();
        }
        class Worker
        {
         public void Advise(IWorkerEvents events) //【譯注:現在傳遞的參數類型為
        接口引用】
        {
        _events = events;
        }
         public void DoWork()
         {
        Console.WriteLine("Worker: work started");
        if( _events != null ) _events.WorkStarted();
        Console.WriteLine("Worker: work progressing");
        if(_events != null ) _events.WorkProgressing();
        Console.WriteLine("Worker: work completed");
        if(_events != null )
         {
        int grade = _events.WorkCompleted();
        Console.WriteLine("Worker grade = " + grade);
         }
         }
         private IWorkerEvents _events;
        }
        class Boss : IWorkerEvents //【譯注:Boss實現該接口】
        {
         public void WorkStarted(){ /*boss不關心. */ }
         public void WorkProgressing(){ /*boss不關心. */ }
         public int WorkCompleted()
         {
        Console.WriteLine("It's about time!");
         return 3; /* out of 10 */
         }
        }
        class Universe
        {
         static void Main()
         {
         Worker peter = new Worker();
         Boss boss = new Boss();
        peter.Advise(boss); //【譯注:或peter.Advise((IWorkerEvents)boss);

        peter.DoWork();
        Console.WriteLine("Main: worker completed work");
        Console.ReadLine();
         }
        }
        /*【譯注:以下是上段程序輸出結果:
        Worker: work started
        Worker: work progressing
        Worker: work completed
        It's about time!
        Worker grade = 3
        Main: worker completed work
        】*/
        委托
         不幸的是,由于peter忙于通知boss實現這個接口,以至于沒有顧得上通知univer
        se也實現該接口,但他知道不久就需如此,至少,他已經抽象了對boss的引用,因此,
        別的實現了IworkerEvents接口的什么人都可以收到工作進度通知。【譯注:請參見上一
        節代碼示例及譯注】
         然而,peter的boss依然極度不滿,“Peter!”boss咆哮者,“你為什么要通知我
        什么時候開始工作、什么時候正在進行工作?我不關心這些事件,你不但強迫我實現這
        些方法,你還浪費了你的寶貴的工作時間等我從事件中返回。當我實現的方法需占用很
        長時間時,你等我的時間也要大大延長!你難道不能想想別的辦法不要老是來煩我嗎?

         此時,peter意識到盡管在很多情況下接口很有用,但在處理事件時,接口的粒度
        還不夠精細。他還要能做到僅僅通知監聽者真正感興趣的事件。因此,peter決定把接口
        里的方法肢解成若干個獨立的委托函數,每一個都好象是只有一個方法的小接口。
        using System; //【譯注:譯者補充】
        delegate void WorkStarted();
        delegate void WorkProgressing();
        delegate int WorkCompleted();
        class Worker
        {
         public void DoWork()
         {
        Console.WriteLine("Worker: work started");
        if( started != null ) started();
        Console.WriteLine("Worker: work progressing");
        if( progressing != null ) progressing();
        Console.WriteLine("Worker: work completed");
        if( completed != null )
         {
        int grade = completed();
        Console.WriteLine("Worker grade = " + grade);
         }
         }
         public WorkStarted started; //【譯注:這樣寫更規矩:public WorkStarted
        started = null;】
         public WorkProgressing progressing; //【譯注:這樣寫更規矩:public Work
        Progressing progressing = null;】
         public WorkCompleted completed; //【譯注:這樣寫更規矩:public WorkComp
        leted completed = null;】
        }
        class Boss
        {
         public int WorkCompleted()
         {
        Console.WriteLine("Better...");
         return 4; /* out of 10 */
         }
        }
        class Universe
        {
         static void Main()
         {
         Workerpeter = new Worker();
         Boss boss = new Boss();
        peter.completed = new WorkCompleted(boss.WorkCompleted);
        peter.DoWork();
        Console.WriteLine("Main: worker completed work");
        Console.ReadLine();
         }
        }
        /*【譯注:以下是上段程序輸出結果:
        Worker: work started
        Worker: work progressing
        Worker: work completed
        Better...
        Worker grade = 4
        Main: worker completed work

        */
        【譯注:對“但在處理事件時,接口的粒度還不夠精細”的理解可用下例說明,請仔細
        觀察一下程序,思考一下這樣做的不利之處J
        using System;
        interface IWorkStartedEvent
        {
         void WorkStarted();
        }
        interface IWorkProgressingEvent
        {
         void WorkProgressing();
        }
        interface IWorkCompletedEvent
        {
         int WorkCompleted();
        }
        class Worker
        {
        public void Advise(IWorkCompletedEvent AEvent)
        {
        _event = AEvent;
        }
        public void DoWork()
        {
        Console.WriteLine("Worker: work completed");
        if(_event != null )
         {
        int grade = _event.WorkCompleted();
        Console.WriteLine("Worker grade = " + grade);
        }
        }
        private IWorkCompletedEvent _event;
        }
        class Boss : IWorkCompletedEvent
        {
        public int WorkCompleted()
        {
        Console.WriteLine("Better...");
        return 4; /* out of 10 */
        }
        }
        class Universe
        {
        static void Main()
         {
         Worker peter = new Worker();
         Boss boss = new Boss();
        peter.Advise(boss);
        peter.DoWork();
        Console.WriteLine("Main: worker completed work");
        Console.ReadLine();
         }
        }
        /*以下是上段程序輸出結果:
        Worker: work completed
        Better...
        Worker grade = 4
        Main: worker completed work
        */

        靜態監聽者
         這就達到了不用boss不關心的事件去煩他的目標。但是,peter還是不能夠使univ
        erse成為其監聽者。因為universe是一個全封閉的實體,所以將委托掛鉤在universe的
        實例上不妥的(設想一下Universe的多個實例需要多少資源...)。peter意識到應將委
        托掛鉤于universe的靜態成員上,因為委托也完全適應于靜態成員:
        using System;
        delegate void WorkStarted();
        delegate void WorkProgressing();
        delegate int WorkCompleted();
        class Worker
        {
         public void DoWork()
         {
        Console.WriteLine("Worker: work started");
        if( started != null ) started();
        Console.WriteLine("Worker: work progressing");
        if( progressing != null ) progressing();
        Console.WriteLine("Worker: work completed");
        if( completed != null )
         {
        int grade = completed();
        Console.WriteLine("Worker grade= " + grade);
         }
         }
         public WorkStarted started = null;
         public WorkProgressing progressing = null;
         public WorkCompleted completed = null;
        }
        class Boss
        {
         public int WorkCompleted()
         {
        Console.WriteLine("Better...");
         return 4; /* out of 10 */
         }
        }
        //【譯注:以上代碼為譯者補充】
        class Universe
        {
        static void WorkerStartedWork()
        {
        Console.WriteLine("Universe notices worker starting work");
        }
        static int WorkerCompletedWork()
        {
        Console.WriteLine("Universe pleased with worker's work");
        return 7;
        }
        static void Main()
        {
        Worker peter = new Worker();
        Boss boss = new Boss();
        peter.completed = new WorkCompleted(boss.WorkCompleted); //【譯注:×

        peter.started = new WorkStarted(Universe.WorkerStartedWork);
        peter.completed = new WorkCompleted(Universe.WorkerCompletedWork);//
        【譯注:這一行代碼使得“×”那一行代碼白做了L】
        peter.DoWork();
        Console.WriteLine("Main: worker completed work");
        Console.ReadLine();
        }
        }
        /*【譯注:以下是上段程序輸出結果:
        Worker: work started
        Universe notices worker starting work
        Worker: work progressing
        Worker: work completed
        Universe pleased with worker's work
        Worker grade = 7
        Main: worker completed work
        】*/
        事件
         不幸的是,universe現在變得太忙并且不習慣于注意某一個人—universe用自己的
        委托取代了peter的boss的委托,這顯然是將Worker類的委托字段設為public的意外的副
        作用。【譯注:請參見上節例子代碼及譯注】同樣地,如果peter的boss不耐煩了,他自
        己就可以觸發peter的委托(peter的boss可是有暴力傾向的)
        // peter的boss自己動手了
        if( peter.completed != null ) peter.completed();
        peter希望確保不會發生這兩種情況。他意識到必須為每一個委托加入注冊和反注冊函數
        ,這樣監聽者就可以添加或移去它們,但誰都不能夠清空整個事件列表。peter自己沒去
        實現這些方法,相反,他使用event關鍵字讓C#編譯器幫他達到這個目的:
        class Worker
        {
        //...
        public event WorkStarted started;
        public event WorkProgressing progressing;
        public event WorkCompleted completed;
        }
         peter懂得關鍵字event使得委托具有這樣的特性:只允許C#客戶用+=或-=操作符添
        加或移去它們自己,這樣就迫使boss和universe舉止文雅一些:
        static void Main()
        {
        Worker peter = new Worker();
         Boss boss = new Boss();
         peter.completed += new WorkCompleted(boss.WorkCompleted);
         peter.started += new WorkStarted(Universe.WorkerStartedWork);
         peter.completed += new WorkCompleted(Universe.WorkerCompletedWork);
        peter.DoWork();
        Console.WriteLine("Main: worker completed work");
        Console.ReadLine();
        }
        【譯注:以下是完整代碼:
        using System;
        delegate void WorkStarted();
        delegate void WorkProgressing();
        delegate int WorkCompleted();
        class Worker
        {
         public void DoWork()
         {
        Console.WriteLine("Worker: work started");
        if( started != null ) started();
        Console.WriteLine("Worker: work progressing");
        if( progressing != null ) progressing();
        Console.WriteLine("Worker: work completed");
        if( completed != null )
         {
        int grade = completed();
        Console.WriteLine("Worker grade = " + grade);
         }
         }
        public event WorkStarted started ;
        public event WorkProgressing progressing;
        public event WorkCompleted completed;
        }
        class Boss
        {
         public int WorkCompleted()
         {
        Console.WriteLine("Better...");
         return 4; /* out of 10 */
         }
        }
        class Universe
        {
         static void WorkerStartedWork()
         {
        Console.WriteLine("Universe notices worker starting work");
         }
         static int WorkerCompletedWork()
         {
        Console.WriteLine("Universe pleased with worker's work");
         return 7;
         }
         static void Main()
         {
         Worker peter = new Worker();
         Boss boss = new Boss();
        peter.completed += new WorkCompleted(boss.WorkCompleted); //【譯注:
        √】
        peter.started += new WorkStarted(Universe.WorkerStartedWork);
        peter.completed += new WorkCompleted(Universe.WorkerCompletedWork);
        peter.DoWork();
        Console.WriteLine("Main: worker completed work");
        Console.ReadLine();
         }
        }
        /*

        以下是上段程序輸出結果:
        Worker: work started
        Universe notices worker starting work
        Worker: work progressing
        Worker: work completed
        Better...// 【譯注:boss也通知到啦J“√”那一行代碼有用啦J,但是且慢,boss打
        的那4分沒有得到,后面只得到了Universe給的7分L】
        Universe pleased with worker's work
        Worker grade = 7
        Main: worker completed work
        */ <>

        溫馨提示:喜歡本站的話,請收藏一下本站!

        本類教程下載

        系統下載排行

        主站蜘蛛池模板: 24小时日本电影免费看| 中文字幕乱码亚洲无线三区| 伊人久久国产免费观看视频| 午夜成年女人毛片免费观看| 亚洲国产综合精品中文第一| 无人在线观看完整免费版视频| ass亚洲**毛茸茸pics| 无码日韩精品一区二区免费| 亚洲kkk4444在线观看| 四虎成人精品一区二区免费网站| 亚洲第一成年免费网站| 国产免费AV片无码永久免费| 成人免费观看男女羞羞视频| 亚洲色无码专区在线观看| 国产成人免费ā片在线观看老同学 | 久久久久国产精品免费免费搜索| 国产精品亚洲片在线va| 在线免费观看国产视频| 又硬又粗又长又爽免费看 | 亚洲第一区香蕉_国产a| 2019中文字幕免费电影在线播放| 亚洲人成网站在线观看播放动漫| 成人免费看吃奶视频网站| 猫咪免费人成网站在线观看入口| 亚洲人成网站18禁止一区| 黄色网站软件app在线观看免费| 亚洲综合无码一区二区| 在线免费视频一区| 一级毛片在线完整免费观看| 亚洲AV本道一区二区三区四区| 在线观看免费人成视频| 免费无码又爽又黄又刺激网站| 亚洲av无码专区国产乱码在线观看| 最近2018中文字幕免费视频| 亚洲av成人无码网站…| 亚洲国产精品无码久久久不卡| 4399好看日本在线电影免费| 一级做a免费视频观看网站| 亚洲精品美女久久久久| 性做久久久久免费观看| 亚洲成人免费在线|