[C#.NET] 委派和事件

  • 6661
  • 0

摘要:[C#.NET] 委派和事件

委派和事件的觀念讓我混淆了許久,今天花了一些時間研究了一下,趕緊把心得記錄下來供日後來參考。

首先,除了微軟的文件庫資料外,獲益最多的就是從C# In Depth網站上看得這篇文章

邊看以下的類別圖邊解釋一下我今天想做的範例,我想建立一個產品類別,當這個產品的庫存數量低於警戒值的時候,需要觸發一個事件來通知使用場景端。我們會看到產品類別分別有公開的:

  1. 屬性:
    • StockAlertLimit - 庫存警戒值
    • StockNumber - 庫存數量
  2. 方法:
    • Purchase() - 購買
  3. 事件:
    • 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("注意,商品數量低於警戒值!");
        }
    }
}

整理一下自己歸納的重點:

  1. 可以將事件想像成是商品類別的屬性,這樣比較好理解
  2. 事件是物件送出訊息的一個方式,透過事件A物件可以告知B物件該事件的發生
  3. 物件可透過事件來告知本身的狀態已經有所改變,在範例裡面我透過商品裡的StockBelowLimitEvent事件來告知使用場景端當庫存數量已經低於警戒值
  4. 委派(delegate)是一種參考型別,用來封裝一個實體的方法,作用就像是指標,可將某方法的參考位置保存在委派裡面
  5. 事件在溝通的時候,事件發送者本身並不知道它自己引發的事件會由哪個物件來處理。
  6. 透過委派來當做橋梁,可讓事件發送者觸發該事件,然後由使用場景端來處理