關於C#中委托的一點理解


C#中委托是一種類型。可以這么籠統的理解:int型變量代表一個整型,而委托類型的變量代表一個方法的地址(將方法名稱傳入constructor並實例化該委托變量)。

--By Brisk Yu

 

1 為何要使用委托

我覺得網上關於什么現實生活的舉例並不好,還是要從程序的本質去理解:

1)程序是由事件驅動的。

2)事件發生時,操作系統需要知道事件對應的處理函數。例如,用戶按下鼠標時操作系統需要知道此時該做什么,是關閉窗口呢,還是打開某個文件呢?當網卡接收到數據包時操作系統也需要知道此時該做什么,是往上層傳輸呢,還是丟棄呢?

3)因此,我們需要將事件對應的處理函數提前告知操作系統(向操作系統注冊),操作系統在發生該事件時,調用對應的處理函數,這便是回調,對應的處理函數也被稱為回調函數

4)那么我們如何向操作系統注冊回調函數呢(如何讓操作系統知道發生對於事件它該干嘛呢)?對於C++,我們使用pointer,而對於C#,我們使用delegate。

 

2 如何使用委托

先從最基本的創建委托的方法開始,逐步變換為使用匿名方法和lambda expression。

1)最原始用法,用方法名初始化一個委托類型變量,調用該委托類型變量,執行承載的方法:

public delegate int SomeDelegate(int i);

int SomeFunction1(int i) { 
    Console.WriteLine("func1"+i);
    return 3; 
}

。。。Main Function
{
    SomeDelegate sd = new SomeDelegate(SomeFunction1);
    sd(2);
}

 

2)如1)中,如果我們使用委托都需要定義一個委托類型比較麻煩,因此我們使用匿名委托:

刪去1)中的

public delegate int SomeDelegate(int i);

並將main function中的代碼改為:

Func<int, int> sd= new Func<int, int>(SomeFunction1);
sd(2);

Func和Action是C#為我們定義好了委托類型。Func指有返回參數的委托類型,其<>中最后一個參數既是返回參數的類型;Action指無返回參數的委托類型。

 

3)既然定義委托類型的代碼可以拿掉,那么相應的方法聲明與定義的語句也可以拿掉:

刪去1)中的方法聲明與定義的語句:

int SomeFunction1(int i) { 
    Console.WriteLine("func1"+i);
    return 3; 
}

將main function 中的代碼改為:

Func<int, int> sd = new Func<int, int>(delegate (int s) { 
    Console.WriteLine("匿名方法" + s); 
    return 88; 
});
int i = sd(2);

此時,Func()中的代碼稱為匿名方法,即沒有方法名。

 

4)我們對3)中的代碼進一步修改,將匿名方法改為lambda表達式。(lambda表達式是匿名方法的一種表示方法)

將mian function中的代碼改為:

Func<int, int> sd = new Func<int, int>(s=> { 
    Console.WriteLine("匿名方法"+s);
    return 88; 
});
int i = sd(2);

此時,對於lambda表達式,編譯器會自動判斷其類型,因此無需特指其類型。

 

3 實際應用

我們參考一下winform中鼠標點擊事件響應是如何實現的

1)在System命名空間中定義一個委托類型

namespace System
{
    //
    // 摘要:
    //     表示將用於處理不具有事件數據的事件的方法。
    //
    // 參數:
    //   sender:
    //     事件源。
    //
    //   e:
    //     不包含事件數據的對象。
    [ComVisible(true)]
    public delegate void EventHandler(object sender, EventArgs e);
}

2)在Control.cs(所有控件的父類)中定義一個EventHandler型的委托Click

public event EventHandler Click;

注:這里用到了event關鍵字,表明這個委托是一個事件。其實是指一簇委托。如果理解不了姑且將event拿掉來看。

 

3)編寫鼠標點擊事件響應代碼

private void buttonStart_Click(object sender, EventArgs e)
{
    //TODO
}

 

4)用3)中方法實例化一個委托賦給Click

this.buttonStart.Click += new System.EventHandler(this.buttonStart_Click);

至此,程序便可以響應buttonStart這個按鈕的響應事件了。更加具體的操作會深入到操作系統中,這里不再敘述。

--By Brisk Yu


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM