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

ASP.NET C# 自訂事件完整實作六步驟教學

     編輯:ASP.NET 基礎

事件模型核心概念

C# 事件基於**委派** 實作,遵循**發布-訂閱** 模式。自訂事件需完成六個步驟:

  1. 宣告委派型別 (定義事件簽名)
  2. 宣告事件成員
  3. 撰寫觸發事件的方法
  4. 撰寫事件處理器 (訂閱端邏輯)
  5. 訂閱事件 (+=)
  6. 觸發事件 (測試驗證)

完整程式碼範例:狗吠事件通知主人

using System;

namespace CustomEventDemo
{
    // 1. 宣告委派:定義事件簽名 (sender, EventArgs)
    public delegate void BarkEventHandler(object sender, BarkEventArgs e);

    // 自訂事件參數:攜帶吠叫時間、聲音大小
    public class BarkEventArgs : EventArgs
    {
        public DateTime Time { get; }
        public int Volume { get; } // 分貝
        public BarkEventArgs(DateTime time, int volume) => (Time, Volume) = (time, volume);
    }

    // 發布者:狗
    public class Dog
    {
        // 2. 宣告事件
        public event BarkEventHandler Bark;

        // 3. 觸發事件的受保護虛擬方法 (慣例命名 On+事件名)
        protected virtual void OnBark(BarkEventArgs e)
        {
            // 線程安全觸發:複製委派再檢查 null
            BarkEventHandler handler = Bark;
            handler?.Invoke(this, e);
        }

        // 業務邏輯:模擬狗吠
        public void SimulateBark(int volume)
        {
            Console.WriteLine($"[Dog] 汪汪! 音量: {volume}dB");
            OnBark(new BarkEventArgs(DateTime.Now, volume));
        }
    }

    // 訂閱者:主人
    public class Host
    {
        public Host(Dog dog)
        {
            // 5. 訂閱事件
            dog.Bark += Dog_Bark;
        }

        // 4. 事件處理器
        private void Dog_Bark(object sender, BarkEventArgs e)
        {
            Console.WriteLine($"[Host] 聽到狗吠! 時間: {e.Time:HH:mm:ss}, 音量: {e.Volume}dB → 起床查看");
        }
    }

    class Program
    {
        static void Main()
        {
            // 6. 測試驗證
            Dog dog = new Dog();
            Host host = new Host(dog);

            dog.SimulateBark(50);
            dog.SimulateBark(80);

            Console.ReadKey();
        }
    }
}

關鍵細節深度解析

委派宣告規範

  • 慣例命名:XXXEventHandler。
  • 參數固定模式:(object sender, XXXEventArgs e),sender 為事件來源,e 攜帶資料。
  • 若無額外資料,直接使用 EventHandler (無泛型) 或 EventHandler<TEventArgs> (泛型,.NET 2.0+)。

事件宣告與封裝

// 編譯器自動產生私有委派欄位 + add/remove 存取器
public event BarkEventHandler Bark;

// 等同於 (手動實作)
private BarkEventHandler _bark;
public event BarkEventHandler Bark
{
    add { _bark += value; }
    remove { _bark -= value; }
}

優勢:外部只能 `+=`/`-=`,**不能直接賦值 `=` 或呼叫 `Invoke`**,保護封裝性。

線程安全觸發模式

protected virtual void OnBark(BarkEventArgs e)
{
    // 1. 取得副本避免競爭條件 (多執行緒同時 -=)
    BarkEventHandler handler = Bark;
    // 2. Null 條件運算子 ?. 呼叫 Invoke
    handler?.Invoke(this, e);
}

.NET 4.5+ 也可用 Volatile.Read(ref _bark)?.Invoke(this, e); 更嚴格保證記憶體可見性。

自訂 EventArgs 設計原則

  • 繼承 System.EventArgs。
  • 屬性唯讀 (init-only 或 getter only),不可變物件模式。
  • 命名以 EventArgs 結尾。

取消訂閱與記憶體洩漏

訂閱者生命週期較長時,**必須在 Dispose/Unload 時 `-=` 取消訂閱**,否則發布者持有委派參考導致訂閱者無法被 GC 回收。

public void Unsubscribe(Dog dog) => dog.Bark -= Dog_Bark;

進階:泛型 EventHandler 簡化委派宣告

// 無需自訂委派型別
public event EventHandler Bark;

// 觸發
EventHandler handler = Bark;
handler?.Invoke(this, new BarkEventArgs(DateTime.Now, 60));

總結速查表

步驟關鍵字/語法說明
1. 委派delegate / EventHandler<T>定義簽名
2. 事件event封裝委派,僅允許 +/-
3. 觸發OnXxx / handler?.Invoke線程安全、null 檢查
4. 處理器void Handler(sender, e)符合委派簽名
5. 訂閱obj.Event += Handler可多播
6. 觸發測試呼叫業務方法驗證流程
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved