<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      nicholas.sun`1[生活的本質不是索取,而是奮斗]

      the most important thing in life is not the triumph but the struggle.

      導航

      [翻譯]簡單談談事件與委托

      原文地址:http://www.codeproject.com/csharp/events.asp
      源代碼下載:/Files/edgar-sun/events_src.zip
      演示文件下載:/Files/edgar-sun/events_demo.zip
      作者:Maysam Mahfouzi  
      原文發布日期:2003/8/16
      原文更新日期:2005/5/14

      內容
      介紹
      什么是委托?
      理解事件
      event關鍵字
      結尾

      介紹
         當我設法學習事件與委托時,我閱讀了很多文章去完全地理解它們并使用它們,現在我想把我學到的展現在這里,其中有很多知識你也需要學習。
      什么是委托?
         委托和事件是緊緊聯系在一起的。委托是函數(方法)指針,更確切地說,委托保持方法的引用。
         委托是一個類。當你創建它的實例的時候,你傳遞將被委托調用的方法名(做為委托構造器的參數)。
         每個委托都有一個特征。例如:

      Delegate int SomeDelegate(string s, bool b);

         是一個委托聲明。我之所以說它有一個特征,是因為它都返回一個int類型的值并帶有兩個參數,類型分別為
       string和bool。
         我說過,當你實例化委托時,你傳遞將被委托調用的方法名做為它的構造器參數。重要的一點是只有與委托具有相同特征的方法才能做為其參數。
         看看下面的方法:

      private int SomeFunction(string str, bool bln){}

         你能把這個方法傳遞給SomeDelegate的構造器做參數,因為它們有相似的特征。
      SomeDelegate sd = new SomeDelegate(SomeFunction);
         現在,sd引用了SomeFunction,換句話說,SomeFunction被注冊到了sd。如果你調用sd,那么SomeFunction也將被調用。緊記已注冊方法的含義。后面,我們將引用它。
      sd("somestring"true);

         既然你已經知道怎么使用委托,下面讓我們來理解事件……

      理解事件
         一個按鈕是一個類,當你點擊它的時候,click事件被觸發。
         一個計時器是一個類,每毫秒觸發一個tick事件。
         想要知道發生什么了?讓我們通過一個例子去學習:
         這是一個假定:我們有一個類Counter。這個類有一個CountTo(int counTo,int reachableNum)方法,從0到countTo計數,并且只要計數到reachableNum這個數時會觸發一個NumberReached事件。
         我們的類有一個事件:NumberReached。事件是委托的變量。我的意思是,如果你聲明一個事件,同時也聲明某一類型的委托,并且要把event關鍵字放在聲明前面,看起來應該是這樣的:

      public event NumberReachedEventHandler NumberReached;

         在上面的聲明中,NumberReachedEventHandler只是一個委托。也許它更應該叫NumberReachedDelegate,但是注意到微軟并沒叫MouseDelegate或PaintDelegate,而是叫MouseEventHandler或PaintEventHandler。把它命名為NumberReachedEventHandler而不是NumberReachedDelegate,這只是一個慣例,了解?很好!
         你了解了我們聲明事件前,需要先定義相應的委托(事件處理者)。它看起來可能是這樣的:

      public delegate void NumberReachedEventHandler(object sender, 
          NumberReachedEventArgs e);

         如你所見,我們委托的名字是:NumberReachedEventHandler,它的特征是返回一個void值,兩個參數類型分別為object和NumberReachedEventArgs。如果你在某處實例化這個委托時,你所傳遞的方法必須和它具有一樣的特征。
         在你的代碼中,你使用過MouseEventArgs或PaintEventArgs去確定鼠標的位置,它在向哪移動,或某個物體的圖形屬性觸發Paint事件么?實際上,在從EventArgs類繼承的類中我們提供給使用者我們的數據。例如,在我們的例子中,我們提供那個可達的數。下面是這個類的聲明:

      public class NumberReachedEventArgs : EventArgs
      {
          
      private int _reached;
          
      public NumberReachedEventArgs(int num)
          {
              
      this._reached = num;
          }
          
      public int ReachedNumber
          {
              
      get
              {
                  
      return _reached;
              }
          }
      }

         如果不需要提供給使用者任何信息,我們可以直接使用EventArgs類。
         現在,所有的事都已經準備好了,下面讓我們來看一下Counter類的內部實現:

      namespace Events
      {
          
      public delegate void NumberReachedEventHandler(object sender, 
              NumberReachedEventArgs e);

          
      /// <summary>
          
      /// Summary description for Counter.
          
      /// </summary>
          public class Counter
          {
              
      public event NumberReachedEventHandler NumberReached;
              
              
      public Counter()
              {
                  
      //
                  
      // TODO: Add constructor logic here
                  
      //
              }
              
      public void CountTo(int countTo, int reachableNum)
              {
                  
      if(countTo < reachableNum)
                      
      throw new ArgumentException(
                          
      "reachableNum should be less than countTo");
                  
      for(int ctr=0;ctr<=countTo;ctr++)
                  {
                      
      if(ctr == reachableNum)
                      {
                          NumberReachedEventArgs e 
      = new NumberReachedEventArgs(
                              reachableNum);
                          OnNumberReached(e);
                          
      return;//don't count any more
                      }
                  }
              }

              
      protected virtual void OnNumberReached(NumberReachedEventArgs e)
              {
                  
      if(NumberReached != null)
                  {
                      NumberReached(
      this, e);//Raise the event
                  }
              }
          }

         在上面的代碼中,如果到達預期的數時就觸發一個事件。在這里我們需要考慮很多事情:
         1、觸發一個事件是通過調用我們的事件(NumberReachedEventHandler的一個實例)完成的。

      NumberReached(this, e);

         這樣,所有已注冊的方法都將被調用。
         2、我們給已注冊的方法數據通過以下代碼:

      NumberReachedEventArgs e = new NumberReachedEventArgs(reachableNum);

         3、一個問題:我們為什么通過OnNumberReached(NumberReachedEventArgs e)方法間接的調用NumberReached(this,e)事件?為什么我們不用下面的代碼:

      if(ctr == reachableNum)
      {
          NumberReachedEventArgs e 
      = new NumberReachedEventArgs(reachableNum);
          
      //OnNumberReached(e);
          if(NumberReached != null)
          {
              NumberReached(
      this, e);//Raise the event
          }
          
      return;//don't count any more
      }

         問的好!如果你想知道為何間接調用,請看OnNumberReached方法的特征:

      protected virtual void OnNumberReached(NumberReachedEventArgs e)

            你看到了,它是保護方法,意味著從這個類繼承的類(子類)中它是可以調用的。
            同時它也是虛方法,意味著子類可以改寫它的實現。
      那是非常有用的。想象一下你正在設計一個從Counter類繼承的類,通過改寫OnNumberReached方法,可以在事件觸發之前方便的增加一些附加的工作。例如:

      protected override void OnNumberReached(NumberReachedEventArgs e)
      {
          
      //Do additional work
          base.OnNumberReached(e);
      }

         注意如果你不調用base.OnNumberReached(e),那么事件永遠也不會觸發。當你繼承了一些類時,你可能想要去除一些事件,這時這樣也許就有用了。有趣的竅門,哈?
         一個真實的例子,當你創建一個新的ASP.NET 應用程序時,你去看看后臺產生的代碼,你會發現你的頁面繼承自System.Web.UI.Page類,而且有一個叫OnInit的保護虛方法。其中在里面有一個InitializeComponent()方法被調用用來做一些附加的工作,然后再調用基類的OnInit(e)方法:

      #region Web Form Designer generated code
      protected override void OnInit(EventArgs e)
      {
          
      //CODEGEN: This call is required by the ASP.NET Web Form Designer.
          InitializeComponent();
          
      base.OnInit(e);
      }
      /// <summary>
      /// Required method for Designer support - do not modify
      /// the contents of this method with the code editor.
      /// </summary>
      private void InitializeComponent()
      {
            
      this.Load += new System.EventHandler(this.Page_Load);
      }
      #endregion

         4、注意NumberReachedEventHandler委托,它是定義在Counter類外,Events命名空間內的,對所有類都可見。
         好了,是時候實踐一下我們的Counter類了。
         在我們的應用程序中,我們有兩個文本框:txtCountTo和txtReachable

         這里是btnRun按鈕點擊事件的事件處理代碼:

      private void cmdRun_Click(object sender, System.EventArgs e)
      {
          
      if(txtCountTo.Text == "" || txtReachable.Text=="")
              
      return;
          oCounter 
      = new Counter();
          oCounter.NumberReached 
      += new NumberReachedEventHandler(
              oCounter_NumberReached);
          oCounter.CountTo(Convert.ToInt32(txtCountTo.Text), 
              Convert.ToInt32(txtReachable.Text));
      }

      private void oCounter_NumberReached(object sender, NumberReachedEventArgs e)
      {
          MessageBox.Show(
      "Reached: " + e.ReachedNumber.ToString());
      }

         這里是初始化某個事件的事件委托的語法:

      oCounter.NumberReached += new NumberReachedEventHandler(
          oCounter_NumberReached);

         現在你應該了解到我們正在做什么。我們初始化了NunberReachedEvnetHandler委托(也可以對其他對象)。注意我上面提及的oCounter_NumberReached方法簽名的相似性。
         現在來看看我們用=代替+=的情形。
         委托是特殊的對象,因為它可以保持多個對象的引用(這里是多個方法)。例如,如果你有另一個方法叫oCounter_NumberReached2,而且簽名和oCounter_NumberReached一樣,那么兩個方法都可以象下面那樣引用:

      oCounter.NumberReached += new NumberReachedEventHandler(
          oCounter_NumberReached);
      oCounter.NumberReached 
      += new NumberReachedEventHandler(
          oCounter_NumberReached2);

         現在,當事件被觸發,一個接一個的方法將被調用。
         如果在你的代碼某處,你不想在NumberReached事件觸發時調用oCounter_NumberReached2,你可以這樣做:

      oCounter.NumberReached -= new NumberReachedEventHandler(
          oCounter_NumberReached2);

      event關鍵字
         許多人也許會問:如果我們不用event關鍵字會怎么樣?
         使用evnet關鍵字可以阻止任何一個委托的使用者把它設為null。為什么這是重要的?想象一下,一個客戶把我類中的其中一個方法注冊到委托調用鏈表,其他客戶也這樣做,這不會出錯。現在,如果有另一客戶用=代替+=給委托新注冊一個方法。這將會把原來的委托調用鏈表清空,并且創建一個全新的單一的委托在委托調用鏈表中。這時其他客戶將無法接收回復信息。關鍵字event正是針對這一問題提出的,如果我在Counter類中加上event關鍵字,并試著編譯下面的代碼,將產生一個編譯器錯誤信息:

         總之,event關鍵字在委托實例上加了一層保護,保護客戶的委托以免被重新設置及委托調用鏈被清空,這樣就只允許對委托調用鏈進行添加或移除操作。
      結尾
         別忘了在你應用程序的構造函數中聲明以下內容,而不是在cmdRun_Click事件處理代碼中。我那樣做僅僅只為了簡單。;-)

      public Form1()
      {
          
      //
          
      // Required for Windows Form Designer support
          
      //
          InitializeComponent();

          
      //
          
      // TODO: Add any constructor code after InitializeComponent call
          
      //
          oCounter = new Counter();
          oCounter.NumberReached 
      += new NumberReachedEventHandler(
              oCounter_NumberReached);
          oCounter.NumberReached 
      += new NumberReachedEventHandler(
              oCounter_NumberReached2);

         提供的源代碼就是這樣子的。

      posted on 2007-12-30 19:53  nicholas.sun  閱讀(228)  評論(0)    收藏  舉報

      主站蜘蛛池模板: 国产日产免费高清欧美一区| 亚洲中文字幕av天堂| 日韩丝袜亚洲国产欧美一区 | 国产av国片精品一区二区| 国产成人精品亚洲一区二区| 国产高清在线男人的天堂| 欧美和黑人xxxx猛交视频| 久久天堂综合亚洲伊人HD妓女| 日韩福利视频导航| 国产精品成熟老女人| 日本熟妇人妻xxxxx人hd| 蜜桃臀av在线一区二区| 临猗县| 欧美巨大极度另类| 无码人妻精品一区二区三区蜜桃 | 日韩精品视频一区二区不卡| 亚洲乱理伦片在线观看中字| 国产精品亚洲二区亚瑟| 亚洲不卡一区三区三区四| 亚洲精品动漫一区二区三| 狠狠色丁香婷婷综合尤物| 国产精品中文字幕在线| 熟女乱一区二区三区四区| 日本一区三区高清视频| 欧美级特黄aaaaaa片| 99精品国产中文字幕| 安陆市| 亚洲成av人片无码不卡播放器 | 综合色一色综合久久网| 亚洲国内精品一区二区| 国产免费网站看v片元遮挡| 国产乱人激情H在线观看| 国产色悠悠在线免费观看| 国产男女猛烈无遮挡免费视频网站| 日韩精品一二三黄色一级| 国产精品三级一区二区三区| 无码精品人妻一区二区三区中| 99久久精品美女高潮喷水| 欧美奶涨边摸边做爰视频| 蜜桃视频一区二区在线观看| 精品免费看国产一区二区|