C#中的委託是什嗎?事件是不是一種委託?

來源:互聯網
上載者:User

本節內容參考《你必須知道的.NET》和《C#進階編程(第四版)》

 

一、瞭解委託

      我們知道回呼函數實際上就是方法調用的指標,也就是通常所說的函數指標。那麼在.NET中,以委託的方式來實現了函數指標的概念。.NET中使用委託的主要原因是它是型別安全的,為什麼呢?因為在以前,比如C中,函數指標只不過是一個指向儲存單元的指標,我們無法說出這個指標實際指向什麼,而委託確定了指向方法的傳回值類型和參數列表。注意的是:委託並不等同於方法,而是一個參考型別。

 

一、委託的定義

委託的定義
       //第1步:聲明一個委託
        public delegate void CalculateDelegate(int x, int y);

        //第2步:建立與委託關聯的方法,二者具有相同的傳回值類型和參數列表
        public void Add(int i, int j)
        {
            MessageBox.Show((i+j).ToString());
        }

        //第3步:定義委託類型變數
        private CalculateDelegate myDelegate;

        public void GetDelegateEx()
        {
            //第4步:進行委託綁定
            myDelegate = new CalculateDelegate(Add);

            //第5步:回調Add方法
            myDelegate(1, 2);
        }

 

 三、多播委託

       在多播委託中需要注意兩點:

     (1)+=和-=操作,其實它們分別調用了Delegate.Combine和Delegate.Remove方法

     (2)多播委託的傳回值一般為Void,如果委託類型為非Void類型,那麼多播委託將返回最後一個調用的方法的執行結果,實際中不推薦這樣應用。

 

 四、委託的本質

       前面我們提到過委託是一個參考型別,其本質上它是一個類,把上邊的代碼編譯為IL:

 

 

       從中我們可以看出:

      (1)委託CalculateDelegate是一個類,它繼承自System.MulticastDelegate

      (2)CalculateDelegate的建構函式:在建立一個委託類型執行個體時,將會為其初始化一個指向對象的引用(這裡指向DelegateEx對象)和一個標識回調方法的整數,由編譯器完成。

      (3)真正執行調用的是Invoke方法。

 

五、委託和事件 

      從前面的範例程式碼中可以看出,在用戶端我們可以隨意對委託進行操作,這在一定程度上破壞了物件導向的封裝機制。.NET的事件模型建立在委託機制之上,它實現了對委託的封裝。

      事件發送器:可以是應用程式中的一個對象或程式集等,主要作用是引發事件。

      事件接收器:發生某些事情時被通知的任何應用程式、對象或組件。

      發送器怎麼通知接收器呢?我們在事件接收器的某個地方定義一個方法,它負責處理事件, 在每次發生登入的事件時,就執行這個事件處理常式。由於發送器對接收器一無所知,這時就要使用委託作為中介。發送器定義接收器要使用的委託,接收器將事件處理常式註冊到事件中。

      先瞭解一下這段代碼:btnSave.Click += new EventHandler(btnSave_Click)。我們在程式設計中經常見到,它告訴我們:在引發btnSave按鈕的Click事件時,應執行btnSave_Click方法。EventHandler是事件用於把處理常式(btnSave_Click)賦予事件(Click )的委託。

Code
    //定義一個內部事件參數類型,用於存放當事件引發時向處理常式傳遞的狀態資訊。
    public class CalculateEventArgs : EventArgs
    {
        public readonly int x, y;

        public CalculateEventArgs(int x,int y)
        {
            this.x = x;
            this.y = y;
        }
    }

    //聲明事件委託。
    public delegate void CalculateEventHandler(object sender, CalculateEventArgs e);

    public class Calculator
    {
        //定義事件成員,提供非正規繫結。
        public event CalculateEventHandler MyCalculate;

        //定義負責通知事件引發的方法,也就是委託的Invoke方法調用。
        protected virtual void OnCalculate(CalculateEventArgs e)
        {
            if (MyCalculate != null)
            {
                MyCalculate(this, e);
            }
        }

        //調用該方法就表示有新的事件方法。
        public void Calculate(int x, int y)
        {
            CalculateEventArgs e = new CalculateEventArgs(x, y);
            
            //通知所有的事件的註冊者
            OnCalculate(e);
        }
    }

 

           

上面定義了一個完整的事件程式,現在只需定義個事件觸發程式。
    public class CalculaterManager
    {
        public void Add(object sender, CalculateEventArgs e)
        {
            MessageBox.Show((e.x + e.y).ToString());
        }
    }

    static void Main()
        {
            Calculator calculator = new Calculator();

            CalculaterManager manager = new CalculaterManager();

            calculator.MyCalculate += manager.Add;
            calculator.Calculate(1, 2);
        }

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.