在 C# 中,事件機制建立在委派之上。若要為類別建構事件,必須先使用 delegate 關鍵字定義一個委派類型,再以 event 關鍵字宣告該類型的欄位。這雙重機制確保了型別安全,並限制外部只能訂閱或取消訂閱,而不能直接觸發事件。
public class Test
{
// 1. 定義委派類型
public delegate void EventHandler(object sender, EventArgs e);
// 2. 宣告事件
public event EventHandler Load;
}
建立類別實例後,使用 += 運算子註冊事件處理常式:
Test m = new Test();
m.Load += new Test.EventHandler(m_Load);
void m_Load(object sender, EventArgs e)
{
MessageBox.Show("這是一個類別事件");
}
以下程式碼示範如何註冊多個處理常式、移除特定訂閱,以及在類別內部觸發事件:
using System;
class TestClass
{
static void Main(string[] args)
{
EventClass myEventClass = new EventClass();
// 註冊兩個處理常式
myEventClass.CustomEvent += new EventClass.CustomEventHandler(CustomEvent1);
myEventClass.CustomEvent += new EventClass.CustomEventHandler(CustomEvent2);
myEventClass.InvokeEvent(); // 觸發兩次
// 移除其中一個
myEventClass.CustomEvent -= new EventClass.CustomEventHandler(CustomEvent2);
myEventClass.InvokeEvent(); // 僅觸發一次
myEventClass.Load += new EventClass.CustomEventHandler(Load1);
myEventClass.OnLoad();
}
private static void CustomEvent1(object sender, EventArgs e)
{
Console.WriteLine("觸發事件 1");
}
private static void CustomEvent2(object sender, EventArgs e)
{
Console.WriteLine("觸發事件 2");
}
private static void Load1(object sender, EventArgs e)
{
Console.WriteLine("目前背景色為 {0},請輸入:", Console.BackgroundColor.ToString());
}
}
public class EventClass
{
// 定義委派類型
public delegate void CustomEventHandler(object sender, EventArgs e);
// 宣告兩個事件
public event CustomEventHandler CustomEvent;
public event CustomEventHandler Load;
public void InvokeEvent()
{
// 安全觸發:檢查是否有訂閱者
CustomEvent?.Invoke(this, EventArgs.Empty);
}
public void OnLoad()
{
Console.BackgroundColor = ConsoleColor.Red;
Load?.Invoke(this, EventArgs.Empty);
string input = Console.ReadLine();
if (input != "yuping")
{
Console.WriteLine("必須輸入 'yuping' 才能變更!");
}
else
{
Console.BackgroundColor = ConsoleColor.Black;
Console.Clear();
}
}
}
正確使用委派必須遵循三個步驟:
public delegate void CustomEventHandler(object sender, EventArgs e);public event CustomEventHandler CustomEvent;InvokeEvent() 方法中透過 CustomEvent(this, EventArgs.Empty); 觸發Invoke),外部只能 += / -=?.Invoke 可避免無訂閱者時擲出 NullReferenceException