[C#] 使用委派自訂事件

入門程式一段時間後,有機會遇到 "委派" 與 "事件"

我自己也常被 這兩個東西搞得很亂。

因為有了事件,所以當事件觸發的時候,程式會跳去處理事件。

(我第一次用偵錯模式逐行執行的時候,直接被嚇一跳)

網路上有許多說明委派與事件的文章,希望我的文章能幫助到你。

若看我的文章還是不太清楚,我建議你先去看這個教學影片 ,有分上、中、下都講得很明白 (對我來說

首先,要完成 "事件" 一系列過程 必須有下面5個關鍵部分

  1. 物件: 手機(擁有事件)
  2. 事件: 手機的鈴響 (通知有訂閱的人)
  3. 事件參數 EventArgs: 來電的電話號碼
  4. 事件處理器 EventHanlder: 電話響起後要做些甚麼
  5. 事件訂閱: 將事件與事件處理器 串接起來,類似委託基礎的約定

整理串聯起來就會發生下面的事情:

"手機" 是一個物件,它擁有 "鈴響" 這個事件。

有一天,我買了手機,當手機鈴響時,我會收到通知。

(可以想像成 我 "訂閱" 了這台手機的鈴響事件。別台手機的鈴響我是不會收到通知的)

當鈴響發生時, 我可以藉由事件處理參數 "來電號碼" 來決定我要怎麼做 (接起來 或 掛掉電話)

 

下面寫一段簡單的程式範例

大致順序是: 製作事件參數 -> 定義事件委託 -> 製作擁有事件的類別&事件 -> 製作要訂閱的類別  -> 進入主程式執行

//宣告事件參數,要繼承EventArgs !!
public class BellEventArgs : EventArgs  
{
	public string Number { get; set; }
}

//定義事件委託
public delegate void BellEventHandler(Phone phone, BellEventArgs e);

	
public class Phone
{
	public event BellEventHandler Bell; //定義事件名稱,此時Phone擁有了Bell事件。
	public void BeCall()
	{
		if (this.Bell != null)          //判斷事件有無被訂閱
		{
			BellEventArgs e = new BellEventArgs();
			e.Number = "09123";
			this.Bell.Invoke(this, e);  //觸發事件

			e.Number = "09321";
			this.Bell.Invoke(this, e);  //觸發事件
		}
	}
}

public class Man
{
	public void Action(Phone phone, BellEventArgs e)
	{
		if (e.Number == "09123")
		{
			Console.WriteLine("不接09123的電話");
		}
		else
		{
			Console.WriteLine("您好! 請問你哪位?");
		}
	}
}

private static void Main(string[] args)
{
	Man man = new Man();
	Phone iphone = new Phone();
	iphone.Bell += man.Action;  // 訂閱事件  (事件 += 事件處理器)

	iphone.BeCall();

	Console.ReadLine();
}

補充說明

若你是去看別人的程式碼,可能會發現別人的訂閱方式 怎麼跟我這邊介紹的不一樣。

那是因為有很多種 訂閱方式 (真令人頭痛)

這邊補充4種不同的訂閱語法,但結果都是一樣的

// button1.Click 是事件

// BottonClick 是事件處理器
private void ButtonClick(object sender, EventArgs e)
{
   this.textBox1.text = "Hi~~";
}



// 1.傳統的訂閱方式
this.button1.Click += new EventHandler(this.ButtonClick);

// 2.新的訂閱方式
this.button1.Click += this.ButtonClick;

// 3.已經被廢棄的匿名訂閱方式
this.button1.Click +=  delegate(object sender, EventArgs e) => {
   this.textBox1.text = "Hi~~";
};

// 4.新的匿名訂閱方式
this.button1.Click += BottonClick(object sender, EventArgs e)
{
   this.textBox1.text = "Hi~~";
}