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

原文鏈接:https://www.cnblogs.com/maomaotou/archive/2011/03/13/1982515.html

一、瞭解委託

      我們知道回調函數實際上就是方法調用的指針,也就是通常所說的函數指針。那麼在.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 )的委託。

 

//定義一個內部事件參數類型,用於存放當事件引發時向處理程序傳遞的狀態信息。
    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);
        }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章