天天看點

C#委托和事件

委托是一種定義方法的類,這樣就可以使得方法A,可以像string類、int類一樣當做方法B的參數進行傳遞。這種将方法動态地指派給參數的做法,可以避免在代碼中大量使用if-else(or switch)語句,同時使得程式具有更好的可擴充性。委托被大量使用在WPF中(至少我是這麼認為的)。但是委托類不同于string類和int類的差別在于,可以将多個方法賦給同一個委托,或者說多個方法可以綁定到同一個委托類上,當調用該委托時,将依次調用其所綁定的方法,但是string類和int類,後面綁定的參數将會替換掉前一個參數。

事件用于封裝委托類。當使用string類時,可以通過屬性對字段進行封裝,某個string類可以隻讀的,也可以是隻寫的。使用event關鍵字,聲明一個事件也就是聲明了一個進行了封裝的委托類型變量,比如下面這條代碼:

public event PropertyChangedEventHandler PropertyChanged;      

其中,PropertyChangedEventHandler是一個委托類,event關鍵字定義了一個封裝該委托的PropertyChanged事件。事件封裝了委托,那麼就可以将方法注冊到事件中,當事件發生時,會依次調用注冊了該事件的方法。比如在WPF中,給一個button控件添加Click方法,其實就是将Btn_Click方法注冊到button控件的Click事件中,即button.Click += Btn_Click.

.NET Framework中對委托和事件編寫的規範:
  • 委托類型的名稱都應該以EventHandler結尾;
  • 委托的傳回值是void(最好),并接受兩個輸入參數,一個是Object類,一個EventArgs類(或繼承自EventArgs);
  • 事件的命名為委托去掉EventHandler之後剩餘的部分;
  • 繼承自EventArgs的類型應該以EventArgs結尾;
  • 訂閱事件的方法命名,通常為On+事件名。

Example:這個例子來源于張子陽部落格中的例子,我最開始學習委托和事件也是看了這篇部落格,是以我的這篇文章算是學習了委托和事件之後的一個整理,目的是加深自己的記憶。張子陽的部落格位址如下:

http://www.tracefact.net/tech/009.html

http://www.tracefact.net/tech/029.html

例子是這樣的,假設有一台熱水器,當加熱到指定溫度時會提醒使用者,則有一個加熱方法,還有一個提醒方法。提醒方法要注冊加熱事件,當溫度達到指定值時,調用提醒方法。

Heater類

public class Heater
    {
        private int temperature;
        // 定義一個名為BoiledEventHandler的委托類,兩個參數,一個object類,一個是繼承自EventArgs類的BoiledEventArgs類
        public delegate void BoiledEventHandler(object sender, BoiledEventArgs e);
        // 定義一個封裝BoiledEventHandler委托的事件
        public event BoiledEventHandler Boiled;

        // 訂閱Boiled事件的方法
        protected virtual void OnBoiled(BoiledEventArgs e)
        {
            // 如果有方法注冊了該事件,則調用所有注冊了該事件的方法
            if (Boiled != null)
                Boiled(this, e);
        }

        // Heater類中有一個加熱的方法
        public void BoilWater()
        {
            for (int i = 0; i <= 100; i++)
            {
                temperature = i;
                if (i % 10 == 0 && i <=95)
                    Console.WriteLine("Temperature is {0}.", i);
                if(temperature > 95)
                {
                    BoiledEventArgs e = new BoiledEventArgs(temperature);
                    OnBoiled(e);
                }
            }
        }
    }      

Alarm類

public class Alarm
    {
        public void MakeAlert(object sender, BoiledEventArgs e)
        {
            Heater heater = sender as Heater;
            Console.WriteLine("Alarm : Temperature is {0}.", e.temperature);
        }
    }      

用戶端程式

class Program
    {
        static void Main(string[] args)
        {
            Heater heater = new Heater();
            Alarm alarm = new Alarm();

            // 将Alarm中的MakeAlert方法注冊到Heater的Boiled事件中
            heater.Boiled += alarm.MakeAlert;

            heater.BoilWater();

            Console.Read();
        }
    }      

觀察者設計模式(observer)

1.Subject,監視對象,它往往包含其他對象所感興趣的内容。在熱水器的例子中,熱水器就是一個監視對象,它包含其他對象感興趣的内容,就是temperature,當這個字段的值接近100的時候,會不斷把資料發給監視它的對象。

2.Observer,監視者,在熱水器的例子中,警報器和顯示器就是監視者,它們要對監視對象中感興趣的内容進行注冊。

Observer設計模式是為了定義對象間的一種一對多的依賴關系,以便于當一個對象的狀态改變時,其他依賴于它的對象會被自動告知并更新。Observer模式是一種松耦合的設計模式。

是以在熱水器的例子中,工作的流程就是,當水溫超過預定值時,将通過委托類分别調用警報器和顯示器中的方法,能夠調用這兩個方法的前提是,它們注冊了封裝該委托類的事件。

c#