首先我們以書中所介紹的委派的由來為起始點展開話題:
在 C 或 C++ 中有時為了開啟一個子執行緒,我們會用到如下的方法:
HANDLE hThread;
DWord ThreadID;
hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadFunc,NULL,0,&ThreadID);
以上語句中的 ThreadFunc() 為 C++ 中的一個全域方法。因為 C++ 或 C 語言都是允許面向過程的,因此全域函數是可以存在的。但大家不妨試想一下,如果是 C# 或 Java 這種純面向物件的語言,我們要怎麼做呢?
思考一下,在 C# 中你可以用如下的程式碼來實現相同的效果嗎?
Thread subThread = new Thread();
subThread.Start(EntryPoint);
這樣做是明顯不對的!在 C++ 中函數名 EntryPoint 實際上就是一個全域函數指標,它表明了子執行緒的入口位址。然而,在 C# 中這樣的情況是絕對不存在的!原因很簡單——作為一門面向物件的語言,C# 中很少有方法是獨立於物件而存在的。
在 C# 中呼叫方法時,這些方法通常都要與一個類別的實例相關聯。也就是說,如果要傳遞一個方法,那麼就必須把該方法的相關細節包裝在一種新型的物件中。於是,伴隨著這種需求,委派隨之誕生。
以上只是《C#高級編程》一書中所提到的委派的產生過程,在這裡我並不想深究其中的機制,而是以此為線索,深層次的挖掘 C# 中委派的實質用途及其優勢所在。
這樣一來,首先單純根據委派的定義可知,委派可以簡單的包裝方法的細節:
1. 簡單的包裝方法
namespace SimpleDelegate
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
// 定義委派
private delegate void MyDelegete();
// 宣告委派的實例變數,並為其掛載相應的方法
private MyDelegete MyObjdelegate = new MyDelegete(MyFun);
private void button1_Click(object sender, EventArgs e)
{
MyObjdelegate();
}
static private void MyFun()
{
MessageBox.Show("委派掛載的事件呼叫成功!");
}
}
}