1、一個例子引發我們的思考:
<span style="font-family:Courier New;font-size:18px;"><span style="font-family:Microsoft YaHei;">using System; usingSystem.Collections.Generic; usingSystem.Text; namespaceDelegate { class Program { //如果此人英國人,英文問候, public void EnglishGreeting(string name) { Console.WriteLine("Morning, " + name); } //如果此人中國人,漢語問候, public void ChineseGreeting(string name) { Console.WriteLine("早上好, " +name); } //枚舉,標識有哪幾種語言。 public enum Language { English, Chinese } //客戶通過此方法,訪問。 public void GreetPeople(string name, Language lang) { //做某些額外的事情,比如初始化之類,此處略 switch(lang) { case Language.English: EnglishGreeting(name); break; case Language.Chinese: ChineseGreeting(name); break; } } static void Main(string[] args) { GreetPeople("張子陽",Chinese); Console.ReadKey(); } } }</span></span>
結果:
早上好,張子陽
從上一個例子就可以知道,調用GreetPeople(“張子陽,Chinese),通過case語句就可以選擇執ChineseGreeting(“張子陽”)。GreetPeople(stringname,Language lang)中的lang參數的參數,其實就是爲了找到對應的方法。爲了辨別那種語言,我們通過枚舉把各個語言都列出,再通過GreetPeople()中case語句選擇匹配客戶的方法。不管我們用枚舉也好,用case也罷,我們的目的就是找到我們要執行的方法。大家是不是會問,我們能不能直接把我們要那個方法傳過去,這樣的話就不會(有枚舉,不會有case)省去很多繁瑣的過程,可謂一步到位。再看GreetPeople(string name, Language lang)此方法定義的時候,都是類型
+變量。那麼現在我們想把我們的方法作爲變量傳過去可行嗎?那麼它的類型又是什麼呢?
2、引入委託
上面的疑問能解決嗎,即下面的方法可以被實現嗎?
public voidGreetPeople(string name, *** MakeGreeting)
{
MakeGreeting(name);
}
接下來就拿上面的例子引入委託:
Publicdelegate void GreetingDelegate(string name);
需要說明兩點
1)定義方法的類型,我們叫它委託。
2)我們定義的委託類型其實和string或int類型有些思想是相同的。他們要修飾變量,類型本身要符合所要修飾變量的一些屬性,這樣的話string類型的數據纔可以放入string定義的空間中,int類型的數據放入int定義的空間內。委託也是一樣的,我們也可以把也是一種修飾類型,開闢此種方法的空間,那麼它一定要適應它修飾方法的一些屬性,這樣的話纔能有做到修飾方法的資格。
下面的方法返回類型爲void,參數類型爲string.
<span style="font-family:Courier New;font-size:18px;"><span style="font-family:Microsoft YaHei;"> public voidEnglishGreeting(string name) { Console.WriteLine("Morning, " + name); } //如果此人中國人,漢語問候, public void ChineseGreeting(string name) { Console.WriteLine("早上好, " +name); }</span></span>
定義此方法的委託,該委託也要符合所修飾方法的返回類型void和參數類型string,的這些屬性。這樣的委託,對於修飾的方法來說纔有意義,得到上面方法的委託是:
Public delegate void GreetingDelegate(string name),GreetingDelegate是此方法的修飾類型。
類型得到了,那麼就可以解決傳參的問題:
public voidGreetPeople(string name, GreetingDelegate MakeGreeting)
{
MakeGreeting(name);
}
應用委託:
<span style="font-family:Courier New;font-size:18px;"><span style="font-family:Microsoft YaHei;">static voidMain(string[] args) { string name1, name2; name1 = "Jimmy Zhang"; name2 = "張子陽"; GreetPeople(name1, EnglishGreeting); GreetPeople(name2, ChineseGreeting); Console.ReadKey(); }</span></span>
結果:
早上好,張子陽
GreetingDelegate MakeGreeting,GreetingDelegate是作爲一個類型而存在的,MakeGreeting變量通過賦值也可以得到,如下:
<span style="font-family:Courier New;font-size:18px;"><span style="font-family:Microsoft YaHei;">static voidMain(string[] args) { GreetingDelegatedelegate1; delegate1 =EnglishGreeting; // 先給委託類型的變量賦值 delegate1 +=ChineseGreeting; // 給此委託變量再綁定一個方法 // 將先後調用 EnglishGreeting 與 ChineseGreeting方法 delegate1("Jimmy Zhang"); Console.ReadKey(); }</span></span>
結果:
Morning, JimmyZhang
早上好, Jimmy Zhang
委託類型的變量可以賦一個值,它可以繼續追加一個值。但是需要注意的是第一次用的“=”,是賦值的語法;第二次,用的是“+=”,是綁定的語法。如果第一次就使用“+=”,將出現“使用了未賦值的局部變量”的編譯錯誤。也可以用下面的形式:
GreetingDelegatedelegate1 = new GreetingDelegate(EnglishGreeting);
delegate1 +=ChineseGreeting; //綁定多個方法,按順序執行。
delegate1 -= EnglishGreeting; //取消對EnglishGreeting方法的綁定
3、總結:
用委託真的很靈活,在你需要的時候引入它,在你不要的時候去掉它。這就是我對委託淺顯的理解,還請給位大牛指導。