事件與索引器是 C# 類型系統中兩項極具表達力的特性。事件實現發布-訂閱模式,支撐鬆耦合通訊;索引器讓對象像數組一樣按索引訪問內部集合,提升 API 直觀性。本文系統講解語法、編譯原理、線程安全、常見陷阱與進階用法。
事件是 delegate 的特殊包裝,僅允許 +=/-= 訂閱/取消訂閱,禁止外部直接調用或賦值 =,保護發布者控制權。
// 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; // 取消訂閱需保持相同委托實例
public/private/protected/internal 控制可見性。(object sender, EventArgs e),sender 為發布者,e 攜帶數據。NullReferenceException。try-catch 或使用 GetInvocationList() 逐個調用捕獲異常。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 { /* 查找或擴展邏輯 */ }
}
}
new/public/protected/internal/private/virtual/sealed/override/abstract/extern。extern 索引器無實現體,僅聲明(用于互操作)。ref/out 參數傳遞。public double this[int row, int col] { get; set; } 用于矩陣、棋盤。get 或 set。interface IRepository { T this[string id] { get; } },實現類隱式/顯式實現。EventHandler<T>,避免自定義委托類型膨脹。EventAggregator / MediatR 解耦跨模塊通訊。