處理和引發事件

文章推薦指數: 80 %
投票人數:10人

事件與EventHandler 委派有關,而且會在名為 OnThresholdReached 的方法中引發。

C# 複製. class Counter { ... 跳到主要內容 已不再支援此瀏覽器。

請升級至MicrosoftEdge,以利用最新功能、安全性更新和技術支援。

下載MicrosoftEdge 其他資訊 目錄 結束焦點模式 語言 閱讀英文 儲存 目錄 閱讀英文 儲存 Twitter LinkedIn Facebook 電子郵件 目錄 處理和引發事件 發行項 07/08/2022 20位參與者 本文內容 .NET中的事件是以委派模型為基礎。

委派模型遵循觀察者設計模式,可讓訂閱者向提供者註冊並接收通知。

事件發送者會推播事件已發生的通知,而事件接收器會收到該通告並定義對它的回應。

本文將描述委派模型的主要元件、如何在應用程式中使用事件,以及如何在程式碼中實作事件。

事件 事件是由物件傳送的訊息,用以表示發生動作。

動作可能是由使用者互動所造成,例如按鈕點選,或可能是因某些其他程式邏輯所造成,例如變更屬性值。

引發事件的物件稱為「事件發送者」。

事件發送者並不清楚哪個物件或方法會接收(處理)它所引發的事件。

事件通常是事件發送者的成員,例如,Click事件是Button類別的成員,而PropertyChanged事件是實作INotifyPropertyChanged介面之類別的成員。

若要定義事件,您可以在事件類別的特徵標記中使用C#的event或VisualBasic的Event關鍵字,並指定事件之委派的型別。

委派將在下一節中描述。

一般而言,若要引發事件,您會加入標記為protected和virtual(C#)或Protected和Overridable(VisualBasic)的方法。

為這個OnEventName方法命名,例如OnDataReceived。

這個方法應該接受一個指定事件資料物件(EventArgs型別或衍生型別之物件)的參數。

您可以提供這個方法讓衍生類別覆寫引發事件的邏輯。

衍生類別一定要呼叫基底類別的OnEventName方法,以確保註冊的委派收到事件。

下列範例將示範如何宣告名為ThresholdReached的事件。

事件與EventHandler委派有關,而且會在名為OnThresholdReached的方法中引發。

classCounter { publiceventEventHandlerThresholdReached; protectedvirtualvoidOnThresholdReached(EventArgse) { EventHandlerhandler=ThresholdReached; handler?.Invoke(this,e); } //provideremainingimplementationfortheclass } PublicClassCounter PublicEventThresholdReachedAsEventHandler ProtectedOverridableSubOnThresholdReached(eAsEventArgs) RaiseEventThresholdReached(Me,e) EndSub 'provideremainingimplementationfortheclass EndClass 委派 委派是保存方法之參考的類型。

委派是透過特徵標記來宣告,該特徵標記會顯示所參考方法的傳回型別和參數,而且委派只能持有符合其特徵標記之方法的參考。

委派因此相當於type-safe函式指標或回呼。

委派宣告不足以定義委派類別。

委派在.NET中有多種用途。

在事件中,委派是事件來源和處理事件的程式碼之間的媒介(或類似指標的機制)。

將委派類型加入事件宣告中就可以讓委派與事件產生關聯,如上一節的範例所示。

如需委派的詳細資訊,請參閱Delegate類別。

.NET提供了EventHandler和EventHandler委派來支援大多數事件案例。

請針對所有沒有事件資料的事件使用EventHandler委派。

請針對有事件相關資料的事件使用EventHandler委派。

這些委派沒有傳回型別值,而且會接受兩個參數(事件來源的物件和事件資料的物件)。

委派是多播,這表示它們可以保存多個事件處理方法的參考。

如需詳細資訊,請參閱Delegate參考頁面。

委派可讓事件處理更彈性並進行精細的控制。

委派會維護事件的已註冊事件處理常式清單,進而做為引發事件之類別的事件分派者。

對於無法使用EventHandler和EventHandler委派的情況,您可以定義委派。

需要定義委派的情況非常少見,例如,當您必須使用無法辨識泛型的程式碼時。

您會在宣告中以C#的delegate與VisualBasic的Delegate關鍵字標記委派。

下列範例將示範如何宣告名為ThresholdReachedEventHandler的委派。

publicdelegatevoidThresholdReachedEventHandler(objectsender,ThresholdReachedEventArgse); PublicDelegateSubThresholdReachedEventHandler(senderAsObject,eAsThresholdReachedEventArgs) 事件資料 與事件相關聯的資料可以透過事件資料類別提供。

.NET提供了許多事件資料類別,可讓您在應用程式中使用。

例如,SerialDataReceivedEventArgs類別是SerialPort.DataReceived事件的事件資料類別。

.NET遵循的命名模式是以EventArgs作為所有事件資料類型的結尾。

您可以藉由查看事件的委派,判斷與事件相關聯的事件資料類別。

例如,SerialDataReceivedEventHandler委派會包含SerialDataReceivedEventArgs類別做為其中一個參數。

EventArgs類別是所有事件資料類別的基底類型。

EventArgs也是您在事件沒有任何相關資料時使用的類別。

如果您建立的事件主要工作只是通知其他類別有事件發生,而不需要傳遞任何資料,請在委派中加入EventArgs類別做為第二個參數。

您可以在未提供資料時傳遞EventArgs.Empty值。

EventHandler委派會包含EventArgs類別做為參數。

當您要建立自訂事件資料類別時,請建立衍生自EventArgs的類別,然後提供傳遞事件相關資料所需的所有成員。

一般而言,您應該使用與.NET相同的命名模式,並以EventArgs作為事件資料類別名稱的結尾。

下列範例將示範名為ThresholdReachedEventArgs的事件資料類別。

其中包含所引發事件專屬的屬性。

publicclassThresholdReachedEventArgs:EventArgs { publicintThreshold{get;set;} publicDateTimeTimeReached{get;set;} } PublicClassThresholdReachedEventArgs InheritsEventArgs PublicPropertyThresholdAsInteger PublicPropertyTimeReachedAsDateTime EndClass 事件處理常式 若要回應事件,請在事件接收器中定義事件處理常式方法。

這個方法必須符合您要處理之事件的委派簽章。

在事件處理常式中,您會在事件引發時執行必要的動作,例如,在使用者按一下按鈕後收集使用者輸入。

若要在事件發生時收到通告,則事件處理常式方法必須訂閱事件。

下列範例將示範名為c_ThresholdReached的事件處理常式方法,該方法會比對EventHandler委派的簽章。

方法會訂閱ThresholdReached事件。

classProgram { staticvoidMain() { varc=newCounter(); c.ThresholdReached+=c_ThresholdReached; //provideremainingimplementationfortheclass } staticvoidc_ThresholdReached(objectsender,EventArgse) { Console.WriteLine("Thethresholdwasreached."); } } ModuleModule1 SubMain() DimcAsNewCounter() AddHandlerc.ThresholdReached,AddressOfc_ThresholdReached 'provideremainingimplementationfortheclass EndSub Subc_ThresholdReached(senderAsObject,eAsEventArgs) Console.WriteLine("Thethresholdwasreached.") EndSub EndModule 靜態和動態事件處理常式 .NET可讓訂閱者以靜態或動態方式註冊事件通知。

靜態事件處理常式在其處理事件之類別的整個生命週期內都有效。

動態事件處理常式會在程式執行期間明確地啟動及停用,通常是為了回應某些條件式邏輯。

比方說,如果只有在某些情況下才需要事件通知,或如果應用程式提供多個事件處理常式且執行階段條件會定義一個要使用的適當處理常式,即可使用動態事件處理常式。

上一節中的範例示範了如何以動態方式加入事件處理常式。

如需詳細資訊,請參閱事件(inVisualBasic)及事件(inC#)。

引發多個事件 如果您的類別會引發多個事件,編譯器將會為每個事件委派執行個體產生一個欄位。

如果事件數目很大,則可能無法接受每個委派一個欄位的儲存成本。

對於這些情況,.NET提供了事件屬性,可以搭配您選擇的另一種資料結構來儲存事件委派。

事件屬性是由事件存取子伴隨的事件宣告所組成。

事件存取子是您定義用來將事件委派執行個體加入儲存區資料結構或從其中移除的方法。

請注意,事件屬性會比事件欄位來得慢些,因為每個事件委派都必須先擷取,然後才能夠叫用。

記憶體和速度之間會有所折衷。

如果您的類別定義許多不常引發的事件,您會想要實作事件屬性。

如需詳細資訊,請參閱如何:使用事件屬性處理多個事件。

相關文章 標題 描述 如何:引發和使用事件 包含引發和使用事件的範例。

如何:使用事件屬性處理多個事件 示範如何使用事件屬性處理多個事件。

觀察者設計模式 描述設計模式,可讓訂閱者向提供者註冊,並且接收通知。

另請參閱 EventHandler EventHandler EventArgs Delegate 事件(VisualBasic) 事件(C#程式設計手冊) 事件和路由事件概觀(UWP應用程式) WindowsStore8.x應用程式中的事件 本文內容



請為這篇文章評分?