C# 事件(上) – 使用委派來實作事件

C#的事件我在ASP.NET MVC中印像中是沒有看過,event應該是在視窗程式或WebForm上才會看到?。不過記得以前寫WebForm的過程中,雖然每個控制項都會用到事件,但記得我不用去了解event也可以把專案做起來,猶豫很久還是決定看看這個主題。

今天的內容主要是參考電子書 C#本事 蔡煥麟

事件驅動

  平常我們撰寫程式時,都是自己主動使用某些物件提供的方法來得到結果。相反地,若物件的結果發生時間是隨機不固定的,我們可能不想自己一直主動詢問物件或一直等待,希望物件結果出來後主動通知我們,而物件結果出來這一件事情就是一種事件、一種改變、一種狀態發生,以上描述的這些算是一種事件驅動的程式設計。在WebForm中,每一個按鈕、控制項都是靠使用者點擊後觸發事件來執行後續程式。

發行-訂閱模式

  C#中的事件處理機制或者說.NET中的事件處理機制,整個機制其實是一種設計模式中–發行-訂閱模式(發行者-訂閱者模式),概念是報社推出一份新報紙,會主動推送給有訂閱報紙的客戶,而不是客戶自己跑去問有沒有新報紙可以買。所以說推出新報紙時、發行新報紙時就會觸發事件,將新報紙送給有訂閱報紙的人。

所以在發行-訂閱模式中,就有幾個關鍵內容

  1. 訂閱者
  2. 發行者
  3. 訂閱名冊
  4. (動作)依名冊通知已經訂閱的人

用委派實作發行/訂閱模式的事件機制

  委派是方法的傳遞,我們可以把方法交給委派,由委派來執行我們的方法。相對地,我們可以把訂閱資料地址等資訊包裝成方法傳遞給委派,當事件發生時執行委派來通知我們這些訂閱者。

先定義一個簡單的訂閱者,每個訂閱者都有名字與自己的通知方法:

class 訂閱者
{
    public string 名字 ;

    public void 通知我(string 訊息)
    {
        Console.WriteLine($"我是{名字},我已經收到最新新聞:{訊息}");
    }
}

接下來再實作發行者,並實作委派來通知訂閱對象
這裡就用C#1.0版的委派使用方式先定義委派

public delegate void 通知對象(string 通知內容);

然後再宣告委派型別作為事件來使用,並且我們再撰寫一個新聞投稿方法,當有人投稿了新聞的那一刻,就要觸發事件去通知訂閱新聞的人。所以我定義了報社類別作為發行者如下:

class 報社
{
    public delegate void 通知對象(string 新聞報導);

    public 通知對象 最新新聞;

    public void 投稿新聞(string 新聞稿)
    {
        //觸發事件
        最新新聞.Invoke(新聞稿);
    }
}

以上我們實作了發行者與訂閱者,並且用委派實作的事件驅動程式

接下來是我們的主程式,包含訂閱新聞與投稿新聞來觸發事件:

static void Main(string[] args)
{
    訂閱者 農夫 = new 訂閱者() { 名字 = "農夫" };
    訂閱者 商人 = new 訂閱者() { 名字 = "商人" };
    訂閱者 騎士 = new 訂閱者() { 名字 = "騎士" };

    報社 王國日報 = new 報社();
    //訂閱
    王國日報.最新新聞 += 農夫.通知我;
    王國日報.最新新聞 += 商人.通知我;
    王國日報.最新新聞 += 騎士.通知我;

    while (true)
    {
        Console.WriteLine("請輸入最新消息:");

        string 消息 = Console.ReadLine();

        王國日報.投稿新聞(消息);
    }

}

執行結果:

退出訂閱

如果要退出訂閱,使用-=

//退出訂閱
王國日報.最新新聞 -= 農夫.通知我;
王國日報.最新新聞 -= 騎士.通知我;

相關文章:
C# 事件(下) – 加上event關鍵字

Facebook留言板