如何發佈符合 .NET 指導方針的事件 (C# 程式設計手冊)
下列程序示範如何將遵循標準 .NET 模式的事件,新增至您的類別和結構。 .NET 類別庫中的所有事件均以如下定義的 EventHandler 委派為基礎:
public delegate void EventHandler(object sender, EventArgs e);
注意
.NET Framework 2.0 引進此委派的泛型版本 EventHandler<TEventArgs>。 下列範例示範如何使用這兩種版本。
雖然您所定義之類別中的事件能以任何有效的委派型別 (甚至是傳回值的委派) 為基礎,但通常建議您使用 EventHandler,讓事件以 .NET 模式為基礎,如下列範例所示。
名稱 EventHandler
可能會導致混淆,因為它實際上不會處理事件。 EventHandler, 和泛型 EventHandler<TEventArgs> 均為委派型別。 簽章符合委派定義的方法或 Lambda 運算式是事件處理常式,並在引發事件時叫用。
發佈以 EventHandler 模式為基礎的事件
(如果您不需要傳送事件的自訂資料,請跳過此步驟,並前往步驟 3a。)以發行者和訂閱者類別可見的範圍,宣告自訂資料的類別。 然後新增必要的成員來保存自訂事件資料。 在此範例中,會傳回一個簡單的字串。
public class CustomEventArgs : EventArgs { public CustomEventArgs(string message) { Message = message; } public string Message { get; set; } }
(如果您要使用 EventHandler<TEventArgs> 的泛型版本,請跳過此步驟。)在發行類別中宣告委派。 指定名稱並以
EventHandler
作為結尾。 第二個參數指定自訂EventArgs
型別。public delegate void CustomEventHandler(object sender, CustomEventArgs args);
使用下列其中一個步驟,在發行類別中宣告事件。
如果沒有自訂 EventArgs 類別,Event 類型將會是非泛型的 EventHandler 委派。 因為當您建立 C# 專案時所包含的 System 命名空間中已宣告委派,所以您不需要宣告委派。 將下列程式碼新增至發行者類別。
public event EventHandler RaiseCustomEvent;
如果您使用的是 EventHandler 的非泛型版本,而且有衍生自 EventArgs 的自訂類別,請在發行類別內宣告事件,並使用步驟 2 中的委派作為類型。
public event CustomEventHandler RaiseCustomEvent;
如果您使用的是泛型版本,則不需要自訂委派。 相反地,您會在發行類別中將事件類型指定為
EventHandler<CustomEventArgs>
,來替代角括號之間的類別名稱。public event EventHandler<CustomEventArgs> RaiseCustomEvent;
範例
下列範例使用自訂 EventArgs 類別和 EventHandler<TEventArgs> 作為事件類型,來示範上述步驟。
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();
}
}
}
另請參閱
意見反應
https://aka.ms/ContentUserFeedback。
即將登場:在 2024 年,我們將逐步淘汰 GitHub 問題作為內容的意見反應機制,並將它取代為新的意見反應系統。 如需詳細資訊,請參閱:提交並檢視相關的意見反應