首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 事件模式實戰:汽車引擎爆炸預警系統完整代碼

     編輯:關於C語言

場景建模:汽車加速與事件通知

設計一個 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}");
    }
}

關鍵設計細節解析

1. 事件的線程安全調用模式


// 標準模式:複製引用後判斷非空再調用,防止多線程競態
var handler = AbortToBlow;
if (handler != null) handler("message");

// C# 6.0+ 空條件操作符簡寫(等價且線程安全)
AbortToBlow?.Invoke("message");

2. 編譯器生成的事件存取器

聲明 public event CarEventHandler AbortToBlow; 時,編譯器生成:

  • 私有委托字段 _abortToBlow
  • add_AbortToBlow:調用 Delegate.Combine 添加訂閱者
  • remove_AbortToBlow:調用 Delegate.Remove 移除訂閱者

這就是為什麼事件只能在類內部觸發(Invoke),外部只能 +=/-=。

3. 訂閱與取消訂閱


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(已報廢持續觸發)

擴展練習:引入 EventArgs 標準模式

生產代碼建議遵循 .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# 觀察者模式的標準實現。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved