<form id="hz9zz"></form>
  • <form id="hz9zz"></form>

      <nobr id="hz9zz"></nobr>

      <form id="hz9zz"></form>

    1. 明輝手游網中心:是一個免費提供流行視頻軟件教程、在線學習分享的學習平臺!

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

      [摘要]作者:Chris Sells 譯者:榮耀 【譯注:C#進階文章。Chris Sells是《ATL Internals》一書作者之一。譯文中所有程 序調試環境均為Microsoft Visual St...
      作者: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的意外的副
      作用!咀g注:請參見上節例子代碼及譯注】同樣地,如果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
      */ <>


      日韩精品一区二区三区高清