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

C# 3.0 筆記:委派與事件——從委派到事件的語法糖演進

     編輯:關於C#

事件是 C# 基於委派的語法糖,簡化了發布-訂閱模式的實作。本文分析事件關鍵字的編譯器生成機制、與委派的關係、標準事件模式、匿名方法訂閱與實戰範例。

事件關鍵字的編譯器生成


public delegate int Calculate(int x, int y);
public event Calculate OnCalculate;

編譯器自動生成:

  • 私有委派欄位:private Calculate OnCalculate;
  • add_OnCalculate 方法:呼叫 Delegate.Combine
  • remove_OnCalculate 方法:呼叫 Delegate.Remove

IL 驗證:add_OnCalculate 內含 call Delegate::Combine,remove_OnCalculate 內含 call Delegate::Remove。

完整事件範例:汽車加速預警


public class EventCar
{
    public delegate void CarEventHandler(string msg);
    public event CarEventHandler AbortToBlow;
    public event CarEventHandler Exploded;

    private const int MaxSpeed = 180;
    public int CurrSpeed { get; private set; }
    public bool IsDead { get; private set; }
    public string Name { get; private set; }

    public EventCar() { }
    public EventCar(string name, int speed)
    {
        Name = name;
        CurrSpeed = speed > MaxSpeed ? MaxSpeed : speed;
        IsDead = speed > MaxSpeed;
    }

    public void Accelerate(int delta)
    {
        if (IsDead)
        {
            Exploded?.Invoke("The Car Is Dead");
            return;
        }
        CurrSpeed += delta;
        if (MaxSpeed - CurrSpeed == 10) 
            AbortToBlow?.Invoke("Careful! Gonna blow!");
        if (CurrSpeed >= MaxSpeed) 
            IsDead = true;
        else 
            Console.WriteLine($"CurrentSpeed: {CurrSpeed}");
    }
}

客戶端訂閱


EventCar bmw = new EventCar("BMW", 110);
bmw.AbortToBlow += CarAboutToBlow;
bmw.Exploded += CarExploded;

for (var i = 0; i < 10; i++)
{
    bmw.Accelerate(20);
    Console.ReadLine();
}

static void CarAboutToBlow(string msg) => Console.WriteLine(msg);
static void CarExploded(string msg) => Console.WriteLine(msg);

標準事件模式

.NET 標準事件委派簽名:


public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e);
public class EventArgs { public static readonly EventArgs Empty = new EventArgs(); }

改造為標準模式


public class CarEventArgs : EventArgs
{
    public string Message { get; }
    public CarEventArgs(string msg) => Message = msg;
}

public event EventHandler<CarEventArgs> AbortToBlow;
public event EventHandler<CarEventArgs> Exploded;

// 觸發
AbortToBlow?.Invoke(this, new CarEventArgs("Careful!"));

匿名方法訂閱事件


// 傳統具名方法
bmw.AbortToBlow += CarAboutToBlow;

// 匿名方法(C# 2.0+)
bmw.AbortToBlow += delegate(object sender, CarEventArgs e) 
{ 
    Console.WriteLine($"Message: {e.Message}"); 
};

// Lambda(C# 3.0+,更簡潔)
bmw.AbortToBlow += (sender, e) => Console.WriteLine($"Message: {e.Message}");

核心總結

  • 事件 = 私有委派欄位 + add/remove 存取子(語法糖)
  • 編譯器自動實作 Delegate.Combine/Remove 實現多播
  • 標準模式:sender + EventArgs 衍生類別
  • 匿名方法/Lambda 簡化單次訂閱邏輯
  • 理解委派本質(MulticastDelegate、GetInvocationList、Combine/Remove)是掌握事件關鍵
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved