下面的過程演示瞭如何將遵循標準 .NET 模式的事件添加到類和結構中。The following procedure demonstrates how to add events that follow the standard .NET pattern to your classes and structs. .NET 類庫中的全部事件均基於 EventHandler 委託,定義以下:All events in the .NET class library are based on the EventHandler delegate, which is defined as follows:express
publicdelegate void EventHandler(object sender, EventArgs e);
備註api
.NET Framework 2.0 引入了泛型版本的委託 EventHandler<TEventArgs>。.NET Framework 2.0 introduces a generic version of this delegate, EventHandler<TEventArgs>. 下例演示瞭如何使用這兩個版本。The following examples show how to use both versions.服務器
儘管定義的類中的事件可基於任何有效委託類型,甚至是返回值的委託,但通常仍是建議使用 EventHandler 使事件基於 .NET 模式,以下例中所示。Although events in classes that you define can be based on any valid delegate type, even delegates that return a value, it is generally recommended that you base your events on the .NET pattern by using EventHandler, as shown in the following example.ide
名稱 EventHandler
可能致使一些混淆,由於它不會實際處理事件。The name EventHandler
can lead to a bit of confusion as it doesn't actually handle the event. EventHandler 和泛型 EventHandler<TEventArgs> 均爲委託類型。The EventHandler, and generic EventHandler<TEventArgs> are delegate types. 其簽名與委託定義匹配的方法或 Lambda 表達式是事件處理程序,並將在引起事件時調用。A method or lambda expression whose signature matches the delegate definition is the event handler and will be invoked when the event is raised.ui
發佈基於 EventHandler 模式的事件Publish events based on the EventHandler pattern
-
(若是無需隨事件一塊兒發送自定義數據,請跳過此步驟轉到步驟 3a。)將自定義數據的類聲明爲對發佈服務器和訂閱者類都可見的範圍。(Skip this step and go to Step 3a if you do not have to send custom data with your event.) Declare the class for your custom data at a scope that is visible to both your publisher and subscriber classes. 而後添加所需成員以保留自定義事件數據。Then add the required members to hold your custom event data. 在此示例中,將返回一個簡單的字符串。In this example, a simple string is returned.this
C#public class CustomEventArgs : EventArgs { public CustomEventArgs(string message) { Message = message; } public string Message { get; set; } }
-
(若是使用的是泛型版本 EventHandler<TEventArgs>,請跳過此步驟。)聲明發布類中的委託。(Skip this step if you are using the generic version of EventHandler<TEventArgs>.) Declare a delegate in your publishing class. 爲其指定以
EventHandler
結尾的名稱。Give it a name that ends withEventHandler
. 第二個參數指定自定義EventArgs
類型。The second parameter specifies your customEventArgs
type.spaC#public delegate void CustomEventHandler(object sender, CustomEventArgs args);
-
使用下列步驟之一來聲明發布類中的事件。Declare the event in your publishing class by using one of the following steps.code
-
若是沒有任何自定義 EventArgs 類,事件類型將爲非泛型 EventHandler 委託。If you have no custom EventArgs class, your Event type will be the non-generic EventHandler delegate. 你無需聲明該委託,由於它已在建立 C# 項目時包括的 System 命名空間中聲明。You do not have to declare the delegate because it is already declared in the System namespace that is included when you create your C# project. 將如下代碼添加到發佈服務器類。Add the following code to your publisher class.orm
C#public event EventHandler RaiseCustomEvent;
-
若是使用非泛型版本 EventHandler 而且具備派生自 EventArgs 的自定義類,請聲明發布類中的事件,並將步驟 2 中的委託用做類型。If you are using the non-generic version of EventHandler and you have a custom class derived from EventArgs, declare your event inside your publishing class and use your delegate from step 2 as the type.事件
C#public event CustomEventHandler RaiseCustomEvent;
-
若是使用泛型版本,則無需自定義委託。If you are using the generic version, you do not need a custom delegate. 而是在發佈類中,將事件類型指定爲
EventHandler<CustomEventArgs>
,替換尖括號中自定義類的名稱。Instead, in your publishing class, you specify your event type asEventHandler<CustomEventArgs>
, substituting the name of your own class between the angle brackets.C#public event EventHandler<CustomEventArgs> RaiseCustomEvent;
-
示例Example
下例經過使用自定義 EventArgs 類和 EventHandler<TEventArgs> 做爲事件類型來演示以前的步驟。The following example demonstrates the previous steps by using a custom EventArgs class and EventHandler<TEventArgs> as the event type.
using System;
namespace DotNetEvents { // Define a class to hold custom event info public class CustomEventArgs : EventArgs { public CustomEventArgs(string message) { Message = message; } public string Message { get; set; } } // Class that publishes an event class Publisher { // Declare the event using EventHandler<T> public event EventHandler<CustomEventArgs> RaiseCustomEvent; public void DoSomething() { // Write some code that does something useful here // then raise the event. You can also raise an event // before you execute a block of code. OnRaiseCustomEvent(new CustomEventArgs("Event triggered")); } // Wrap event invocations inside a protected virtual method // to allow derived classes to override the event invocation behavior protected virtual void OnRaiseCustomEvent(CustomEventArgs e) { // Make a temporary copy of the event to avoid possibility of // a race condition if the last subscriber unsubscribes // immediately after the null check and before the event is raised. EventHandler<CustomEventArgs> raiseEvent = RaiseCustomEvent; // Event will be null if there are no subscribers if (raiseEvent != null) { // Format the string to send inside the CustomEventArgs parameter e.Message += $" at {DateTime.Now}"; // Call to raise the event. raiseEvent(this, e); } } } //Class that subscribes to an event class Subscriber { private readonly string _id; public Subscriber(string id, Publisher pub) { _id = id; // Subscribe to the event pub.RaiseCustomEvent += HandleCustomEvent; } // Define what actions to take when the event is raised. void HandleCustomEvent(object sender, CustomEventArgs e) { Console.WriteLine($"{_id} received this message: {e.Message}"); } } class Program { static void Main() { var pub = new Publisher(); var sub1 = new Subscriber("sub1", pub); var sub2 = new Subscriber("sub2", pub); // Call the method that raises the event. pub.DoSomething(); // Keep the console window open Console.WriteLine("Press any key to continue..."); Console.ReadLine(); } } }