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

C# 事件與索引器深度解析:從原理到最佳實踐

     編輯:關於C#

事件與索引器是 C# 類型系統中兩項極具表達力的特性。事件實現發布-訂閱模式,支撐鬆耦合通訊;索引器讓對象像數組一樣按索引訪問內部集合,提升 API 直觀性。本文系統講解語法、編譯原理、線程安全、常見陷阱與進階用法。

一、事件

1.1 本質:委托的封裝

事件是 delegate 的特殊包裝,僅允許 +=/-= 訂閱/取消訂閱,禁止外部直接調用或賦值 =,保護發布者控制權。

1.2 標準模式

// 1. 定義委托類型 (建議 EventHandler<TEventArgs>)
public delegate void CustomEventHandler(object sender, CustomEventArgs e);

// 2. 聲明事件
public event CustomEventHandler CustomEvent;

// 3. 觸發方法 (線程安全拷貝模式)
protected virtual void OnCustomEvent(CustomEventArgs e)
{
    CustomEventHandler handler = CustomEvent; // 拷貝避免競態
    handler?.Invoke(this, e);
}

// 4. 訂閱者
obj.CustomEvent += (s, e) => Console.WriteLine(e.Message);
obj.CustomEvent -= handler; // 取消訂閱需保持相同委托實例

1.3 關鍵規則

  • 訪問修飾符:public/private/protected/internal 控制可見性。
  • 標準簽名:(object sender, EventArgs e),sender 為發布者,e 攜帶數據。
  • 線程安全觸發:必須拷貝委托字段再判空調用,防止最后一個訂閱者在判空后被移除導致 NullReferenceException。
  • 異常隔離:單個處理器拋出異常會中斷后續處理器,建議處理器內部 try-catch 或使用 GetInvocationList() 逐個調用捕獲異常。

二、索引器

2.1 語法與簽名

public class SampleCollection<T>
{
    private T[] arr = new T[100];
    // 索引器簽名由參數列表決定,不包含返回類型
    public T this[int index]
    {
        get => arr[index];
        set => arr[index] = value;
    }
    // 可重載:字符串索引
    public T this[string key]
    {
        get => arr.FirstOrDefault(x => x?.ToString() == key);
        set { /* 查找或擴展邏輯 */ }
    }
}

2.2 修飾符與約束

  • 允許修飾符:new/public/protected/internal/private/virtual/sealed/override/abstract/extern。
  • extern 索引器無實現體,僅聲明(用于互操作)。
  • 索引器值非變量,不可作 ref/out 參數傳遞。
  • 同一類可定義多個索引器,簽名(參數類型/數量)必須不同。

2.3 進階場景

  • 多維索引器:public double this[int row, int col] { get; set; } 用于矩陣、棋盤。
  • 只讀/只寫:僅實現 get 或 set。
  • 介面中聲明索引器:interface IRepository { T this[string id] { get; } },實現類隱式/顯式實現。

三、實戰建議

  1. 事件優先使用 EventHandler<T>,避免自定義委托類型膨脹。
  2. 大型項目考慮 EventAggregator / MediatR 解耦跨模塊通訊。
  3. 索引器邏輯保持輕量,避免隱藏昂貴操作(如數據庫查詢),違反最小驚訝原則。
  4. 結構體實現索引器時注意值語義:索引器返回副本,修改不影響原結構體數組元素。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved