摘要:[C#.NET] 委派和事件
委派和事件的觀念讓我混淆了許久,今天花了一些時間研究了一下,趕緊把心得記錄下來供日後來參考。
首先,除了微軟的文件庫資料外,獲益最多的就是從C# In Depth網站上看得這篇文章。
邊看以下的類別圖邊解釋一下我今天想做的範例,我想建立一個產品類別,當這個產品的庫存數量低於警戒值的時候,需要觸發一個事件來通知使用場景端。我們會看到產品類別分別有公開的:
-
屬性:
- StockAlertLimit - 庫存警戒值
- StockNumber - 庫存數量
-
方法:
- Purchase() - 購買
-
事件:
- StockBelowLimitEvent - 當產品庫存數量低於警戒值所需處發的事件
接著解釋一下程式的流程,首先在Program裡面建立一個產品類別的物件,並透過產品屬性定義了產品的庫存數量和警戒值,接著呼叫產品類別裡面的購買方法,在購買方法裡會將所購買的數量從產品庫存數量裡扣除,並同時比對庫存數量是否低於警戒值,如低於警戒值時須透過委派實體來傳遞訊息告知Program
我們看一下Product的內容:
namespace DelegateDemo
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
///
/// Product類別,同時也是事件發送者
///
public class Product
{
//1.透過委派(delegate)這個關鍵字來宣告
// 我們定義了一個名稱為ProductEventHandler的委派類別
// ProductEventHandler -> 代表某個事件的處理方法
public delegate void ProductEventHandler();
//2.接著建立事件,這個事件會透過我們之前定義的委派來傳遞訊息給接收端
public event ProductEventHandler StockBelowLimitEvent;
public int StockNumber { get; set; }
public int StockAlertLimit { get; set; }
public void Purchase(int amount)
{
StockNumber = StockNumber - amount;
if (StockNumber <= StockAlertLimit)
{
this.RaiseTheEvent();
}
}
private void RaiseTheEvent()
{
//在傳送訊息給接收端前,發送端需檢查事件是否已註冊
if (StockBelowLimitEvent != null)
{
StockBelowLimitEvent();
}
}
}
}
接著看一下Program的內容:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DelegateDemo
{
class Program
{
static void Main(string[] args)
{
Product p = new Product();
//3.在使用場景端定義了一個方法並塞給Product的事件
// 當此事件被觸發後,使用場景端可針對此事件來處理
p.StockBelowLimitEvent += new Program().StockBelowLimitAlert;
p.StockNumber = 10;
p.StockAlertLimit = 8;
p.Purchase(2);
Console.Read();
}
private void StockBelowLimitAlert()
{
Console.WriteLine("注意,商品數量低於警戒值!");
}
}
}
整理一下自己歸納的重點:
- 可以將事件想像成是商品類別的屬性,這樣比較好理解
- 事件是物件送出訊息的一個方式,透過事件A物件可以告知B物件該事件的發生
- 物件可透過事件來告知本身的狀態已經有所改變,在範例裡面我透過商品裡的StockBelowLimitEvent事件來告知使用場景端當庫存數量已經低於警戒值
- 委派(delegate)是一種參考型別,用來封裝一個實體的方法,作用就像是指標,可將某方法的參考位置保存在委派裡面
- 事件在溝通的時候,事件發送者本身並不知道它自己引發的事件會由哪個物件來處理。
- 透過委派來當做橋梁,可讓事件發送者觸發該事件,然後由使用場景端來處理