2013年4月9日 星期二

[C#]Delegate

如果你有學過C,C#的delegate其實很類似C的function pointer。delegate讓我們可以把function透過參數的形式來傳遞,也就是說delegate可以讓我們把function當作first class opject來操作。下列是一個delegate的簡單範例:
using System;
delegate void StringProcessor(string input);
class Person
{
    string name;
    public Person(string name) { this.name = name; }
    public void Say(string message)
    {
        Console.WriteLine("{0} says: {1}", name, message);
    }
}

class SimpleDelegateUse
{
    static void Main()
    {
        Person jon = new Person("Jon");
        Person tom = new Person("Tom");
        StringProcessor jonsVoice, tomsVoice;
        jonsVoice = new StringProcessor(jon.Say);
        tomsVoice = new StringProcessor(tom.Say);
        jonsVoice("Hello, son.");
        tomsVoice.Invoke("Hello, Daddy!");
    }
}
此範例中我們建立了宣告了兩個delegate的instance,分別是jonsVoice以及tomsVoice。最後用兩種不同的方式呼叫function
使用delegate要有以下三個步驟:

1. 宣告delegate type
delegate void StringProcessor(string input);
這行就是我們宣告delegate type的地方,這個delegate的type是含有一個string參數且回傳值為void的function。此delegate type只能接受回傳值以及參數個數一模一樣的function。不過有一種特殊情況:
void Test(object x);
此function也可以被assigned給此delegate的instance,因為string是繼承自object

2. 建立delegate instance
StringProcessor jonsVoice, tomsVoice;
jonsVoice = new StringProcessor(jon.Say);
用new可以建立剛才宣告好得delegate instance,建立傳入的參數是之後要透過delegate呼叫的function

3. 呼叫delegate instance的function

編譯之後會把jonsVoice("Hello, son.")轉成jonsVoice.Invoke("Hello, son.")
最後又會透過delegate呼叫原本assigned的function jon.Say("Hello, son.")

delegate很常用在UI Button的click,我們會事先宣告EventHandler的delegate instance。當button被按下時,執行對應的處理function。有點類似call back function。

每個delegate instance內部都有一個invocation list用來紀錄function,也就是說一個delegate instance可以紀錄不只一個function。當有多個function時,delegate會一一呼叫invocation list中所儲存的function。我們可以透過+=以及-=運算子來新增移除function。以下是個簡單的範例:

void HowAreYou(string sender) {
  Console.WriteLine("How are you, " + sender + '?');
}
 
void HowAreYouToday(string sender) {
  Console.WriteLine("How are you today, " + sender + '?');
}
 
Notifier greetMe;
 
greetMe = new Notifier(HowAreYou);
greetMe += new Notifier(HowAreYouToday);
 
greetMe("Leonardo");                      // "How are you, Leonardo?"
                                          // "How are you today, Leonardo?"
 
greetMe -= new Notifier(HowAreYou);
 
greetMe("Pereira");                       // "How are you today, Pereira?"

沒有留言:

張貼留言