設計一個 EventCar 類,模擬汽車加速過程:接近極速觸發預警,超速觸發爆炸事件。完整演示委托聲明、事件封裝、標準事件模式實現。
public class EventCar
{
// 1. 定義委托類型:統一事件簽名
public delegate void CarEventHandler(string msg);
// 2. 定義事件:編譯器自動生成 add/remove 存取器
public event CarEventHandler AbortToBlow; // 預警事件
public event CarEventHandler Exploded; // 爆炸事件
// 3. 核心字段與屬性
private const int MaxSpeed = 180;
public int CurrSpeed { get; private set; }
public bool IsDead { get; private set; }
public string Name { get; private set; }
// 4. 構造函數
public EventCar() { }
public EventCar(string carName, int currSpeed)
{
if (currSpeed > MaxSpeed) IsDead = true;
else { Name = carName; CurrSpeed = currSpeed; }
}
// 5. 核心業務邏輯:加速並觸發事件
public void Accelerate(int addSpeed)
{
if (IsDead)
{
// 已報廢:觸發爆炸事件
Exploded?.Invoke("The Car Is Dead");
return;
}
CurrSpeed += addSpeed;
// 接近極速 10 以內:觸發預警
if (MaxSpeed - CurrSpeed == 10 && AbortToBlow != null)
AbortToBlow("Careful! Gonna blow!");
// 達到/超過極速:標記報廢
if (CurrSpeed >= MaxSpeed)
IsDead = true;
else
Console.WriteLine($"CurrentSpeed: {CurrSpeed}");
}
}
// 標準模式:複製引用後判斷非空再調用,防止多線程競態
var handler = AbortToBlow;
if (handler != null) handler("message");
// C# 6.0+ 空條件操作符簡寫(等價且線程安全)
AbortToBlow?.Invoke("message");
聲明 public event CarEventHandler AbortToBlow; 時,編譯器生成:
_abortToBlowadd_AbortToBlow:調用 Delegate.Combine 添加訂閱者remove_AbortToBlow:調用 Delegate.Remove 移除訂閱者這就是為什麼事件只能在類內部觸發(Invoke),外部只能 +=/-=。
var car = new EventCar("Ferrari", 0);
// 訂閱
car.AbortToBlow += msg => Console.WriteLine($"[預警] {msg}");
car.Exploded += msg => Console.WriteLine($"[爆炸] {msg}");
// 取消訂閱(需保持相同委托實例)
car.AbortToBlow -= handler;
var car = new EventCar("TestCar", 170);
car.Accelerate(5); // CurrentSpeed: 175
car.Accelerate(5); // [預警] Careful! Gonna blow! → CurrentSpeed: 180
car.Accelerate(1); // [爆炸] The Car Is Dead
car.Accelerate(10); // [爆炸] The Car Is Dead(已報廢持續觸發)
生產代碼建議遵循 .NET 標準事件模式:
public class CarEventArgs : EventArgs
{
public string Message { get; }
public int CurrentSpeed { get; }
public CarEventArgs(string msg, int speed) { Message = msg; CurrentSpeed = speed; }
}
public event EventHandler SpeedWarning;
public event EventHandler CarExploded;
// 觸發
SpeedWarning?.Invoke(this, new CarEventArgs("Careful!", CurrSpeed));
事件是委托的「受控封裝」:外部只能訂閱/取消,不能任意觸發/清空。標準模式 EventHandler<TEventArgs> + EventArgs 衍生類,配合 ?.Invoke 線程安全調用,是構建鬆耦合通知系統的基石。掌握此模式,即掌握了 C# 觀察者模式的標準實現。