標籤:style blog io ar color 使用 sp strong on
文章目的:作者(初學者)在學習c#的過程中,對事件、委託及其中的“object sender,EventArgs e”一直感覺理解不透,因此在網上找了一些資料,學習並整理出了該篇筆記,希望能將自己的心得記錄下來作為積累。限於能力且是初學,有錯誤的地方還請大家批評指正。
注意:該筆記中有部分內容摘自網上的參考資料,並非作者原創,僅限學習交流,特此聲明!
一. 委託與事件
委託與事件是一對相互關聯的概念。委託是一種參考型別,可通過聲明委託變數,並將其初始化為某個匹配的函數來實現對該函數的引用。事件可以使類或對象向其他類或對象通知發生的相關事情,以使其他類或對象為此做出響應。靈活的事件處理要求將事件的響應指派給相應的事件處理常式(或稱事件處理函數、事件處理方法),而C#中事件處理常式通常都是委託實現的。
二. 委託
1. 定義
委託其實是一種參考型別,它通過聲明一個委託類型的變數,並通過將該變數初始化一個與該委託具有相同傳回值類型和形參列表的函數引用,來實現所謂的對函數的引 用。
2. 聲明方式
modifiers(opt) delegate return-Type identifier (fomal-parameter-list(opt))
修飾符(可選) 委託關鍵字 傳回值類型 標識符 (形參列表(可選))
Public delegate double DataProcess (double x, double y)
3. 使用步驟
1)聲明委託,指定其傳回值類型和形參列表;
2)定義與委託具有相同傳回值類型和形參列表的函數;
3) 聲明委託類型的變數,並將該委託變數初始化為步驟2)中所定義的與該委託具有相同傳回值類型和形參列表的函數引用.
4. 使用舉例
1 public delegate double DataProcess(double x, double y);//聲明委託DataProcess,指定其傳回值類型和形參列表2 class A3 {4 public static double Multiply(double x, double y); //定義與委託具有相同傳回值類型和形參列表的函數Multiply()5 {6 return x*y;7 }8 DataProcess dataProcess = new DataProcess(Multiply);//定義了委託之後,聲明該委託類型的變數dataProcess,接著把這個變數初始化為與委託具有相同傳回值類型和 //形參列表的函數引用Multiply9 }
三. 事件
1. 定義
1)發起者:引發事件的類或對象;
2) 訂戶:處理(或稱“響應”)事件的類或對象;
3) 事件處理常式:訂戶提供的一些代碼,用於在事件被引發時執行(事件處理常式可位於發起者所在的類,也可位於其他類);
4) 訂閱:在發起者引發事件後,執行訂戶的事件處理常式(即將事件處理常式綁定到事件);
5) 事件:事件由發起者引發,由訂戶訂閱,事件被引發後開始執行訂閱該事件的由訂戶所提供的事件處理常式;
2. 聲明方式
modifiers(opt) event Type identifier
修飾符(可選) 委託關鍵字 類型 標識符
Public event EventHanlder Click
四。 事件的分類及其使用步驟
這裡將事件分為兩種:1.NetFrameWork類庫中已經為我們封裝好的事件;2.我們自訂的事件。下面分別說明這兩種事件的使用步驟,並給出程式碼範例:
1.NetFrameWork類庫中封裝好的事件的使用步驟
注意:在.NET Framwork類庫中,事件是基於EventHandler(委託祖類)和EventArgs(事件數目據祖類)兩個基類的。
1)定義委託
委託的定義用於指定訂閱該事件的事件處理常式(或事件處理方法、事件處理函數)的傳回值類型及形參列表(此處以backgroundWorker組件為例);
public delegate void DoWorkEventHandler ( object sender, DoWorkEventArgs e);
a. 傳回值類型:void
b. 參數1:object sender:
是一個對象,其實是一個對象引用,這裡的事件是對象backgroundWorker1的事件,這個對象指的就是backgroundworker1。(backgroundWorker1是B ackgroundWorker類的一個執行個體)。
c. 參數2:DoWorkEventArgs e:
是一個包含事件數目據的對象,用於傳遞事件的細節,DoWorkEventArgs是一個包含事件數目據的類,它繼承自包含事件數目據的基類EventArgs;
注意:委託的傳回值類型和形參列表根據自己的需要定義(包括命名),只要事件處理方法的傳回值和參數與之匹配即可。此外委託並不需要與事件位於同一個類或 命名空間中,它可以位於其他類或命名空間,在.Net Framwork的類庫中就是這樣,自訂事件可根據需要安排。
2)定義事件
1 public event DoWorkEventHandler DoWork;
該事件位於BackgroundWorker類中,所以調用時為this.backgroundWorker1.DoWork,該事件在RunWorkerAsync()函數中引發,該函數也位於 BackgroundWorker類中。
3)定義監聽事件函數(監聽事件函數用於在滿足一定條件時引發事件)
事件DoWork的監聽事件函數是RunWorkerAsync(),該函數已經由.NET在BackgroundWorker類中定義,我們直接用就可以。
4)定義事件處理函數
private void Process(object sender, DoWorkEventArgs e){ Console.writeln(“the event has processed!”);}
注意:要求事件處理函數與委託具有匹配的傳回值類型和參數列表。
5)為事件添加事件處理函數
this.backgroundWorker1.DoWork += new System.ComponentModel.DoWorkEventHandler(Process);
以上便是.net類庫封裝的事件的使用過程,但是事件處理函數的添加一般在組件(或控制項)的屬性中設定即可,另外委託、事件和監聽事件函數.NET Framework類 庫已經為我們定義好,直接用就可以,我們唯一需要做的就是編寫事件處理函數,我們可以在事件處理函數中寫入事件發生時我們想做的事情。
2.自訂事件使用步驟(這裡以一個類來監聽用戶端鍵盤輸入事件為例)
1)定義委託
public delegate void UserRequest(Object sender, EventArgs e);
注意:參數Object用來傳遞事件的發生者,EventArgs用來傳遞事件的細節(該例暫時沒用到)。
2)定義事件 (步驟1)中的委託類型)
public event UserRequest OnUserRequest;
3)定義監聽事件函數
監聽事件函數用於在滿足一定條件時引發事件,監聽事件函數對於在.NET Framwork類庫中封裝的事件已經為我們定義好了,無需我們自己定義。而這裡我們需要自 己定義,此函數相當於事件使用步驟1中的RunWorkerAsync()函數
//該函數不斷要求使用者從鍵盤輸入字元,如果輸入結果為“h”,則引發OnUserRequest事件,事件的引發者是本身(this,即該類(或該類執行個體化對象)),事件細節無(沒有傳遞任何參數給E//ventArgs執行個體),我們給這個類起名為UserInputMonitor。public void run() { bool finished = false; do { if (Console.ReadLine() == "h") { OnUserRequest(this,new EventArgs());//如果使用者鍵盤輸入為“h”,則引發事件 } } while (!finished); }
4)定義事件處理常式(這裡將該函數定義在用戶端類(Client類)中)
首先執行個體化UserInputMonitor類:
UserInputMonitor monitor = new UserInputMonitor();
然後定義事件處理常式
private void ShowMessage(object sender, EventArgs e){ Console.WriteLine("haha");//如果使用者輸入的h,則列印“haha”}
5)將事件處理常式綁定到事件(或稱訂閱事件)
這裡將其寫到Client的建構函式裡
Client(UserInputMonitor m){ m.OnUserRequest += new UserInputMonitor.UserRequest(this.ShowMessage);}
接下來建立用戶端並開始監聽事件
new Client(monitor);//將事件處理方法綁定到事件OnUserRequestmonitor.run();
該自訂事件的全部代碼如下所示(c#控制台程式)
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace ConsoleApplication2{ class Client { //建構函式 Client(UserInputMonitor m) { m.OnUserRequest += new UserInputMonitor.UserRequest(this.ShowMessage);//訂閱事件 } public static void Main(string[] args) { UserInputMonitor monitor = new UserInputMonitor(); new Client(monitor);//將事件處理方法綁定到事件OnUserRequest monitor.run(); } private void ShowMessage(object sender, EventArgs e) { Console.WriteLine("haha"); }} class UserInputMonitor { public delegate void UserRequest(Object sender, EventArgs e);//定義委託 public event UserRequest OnUserRequest;//定義此委託類型的事件 public void run() { bool finished = false; do { if (Console.ReadLine() == "h") { OnUserRequest(this,new EventArgs());//如果使用者鍵盤輸入為“h”,則事件發生 } } while (!finished); } } }
關於c#中委託與事件的一些理解