C#基礎:委託

委託是C#中最爲常見的內容。與類、枚舉、結構、接口同樣,委託也是一種類型。類是對象的抽象,而委託則能夠當作是函數的抽象。一個委託表明了具備相同參數列表和返回值的全部函數。好比:異步

view plaincopy to clipboardprint?
  1. delegate int GetCalculatedValueDelegate(int x, int y);  

在上面的定義中,咱們定義了一個委託,這個委託表明着一類函數,這些函數的第一個參數是整數型的x,第二個參數是整數型的y,而函數的返回值則是一個整數。在這裏,爲了描述方便,咱們把這一類的函數稱爲具備相同簽名(signature)的函數(注意:這個簽名並非數字簽名中的概念,而只是表示這類函數具備相同的參數列表和返回值)。函數

既然委託是一種類型,那麼它就能被用來定義參數、變量以及返回值。由委託定義的變量用於保存具備相同簽名的函數實體。須要注意的是,C#和C++不一樣,C++中的函數指針只能保存全局的或者靜態的函數,而C#中的委託實體則能夠指代任何函數。spa

如今咱們來看一個例子,在這個例子中,咱們使用了上面定義的那個委託,並建立了一個委託實體,使其指代程序中的AddCalculator函數,接下來就能夠直接像使用函數自己同樣,使用這個委託實體來得到計算的結果。線程

view plaincopy to clipboardprint?
  1. delegate int GetCalculatedValueDelegate(int x, int y);   
  2.   
  3. static int AddCalculator(int x, int y)   
  4. {   
  5.     return x + y;   
  6. }   
  7.   
  8. static int SubCalculator(int x, int y)   
  9. {   
  10.     return x - y;   
  11. }   
  12.   
  13. static void Main(string[] args)   
  14. {   
  15.     GetCalculatedValueDelegate d = AddCalculator;   
  16.     Console.WriteLine(d(10, 20));   
  17. }   

到這裏也就能基本上明白「委託」的意義了,針對上面的Main函數,原本須要調用AddCalculator函數的,卻經過d來調用了,也就是,後續對AddCalculator的操做由d代爲效勞。原本是要小明去老師辦公室拿粉筆盒的,因爲小明和小文是好朋友,所以小明就要小文代他去拿,因而小文成了小明的代理,小明委託小文去拿粉筆盒。代理

如今咱們來考慮委託做爲參數的情形。將委託做爲參數,能夠把函數自己的處理邏輯抽象出來,而讓調用者決定最終使用什麼樣的邏輯去處理。請看下面的例子:指針

view plaincopy to clipboardprint?
  1. delegate int GetCalculatedValueDelegate(int x, int y);   
  2.   
  3. static int AddCalculator(int x, int y)   
  4. {   
  5.     return x + y;   
  6. }   
  7.   
  8. static int SubCalculator(int x, int y)   
  9. {   
  10.     return x - y;   
  11. }   
  12.   
  13. static int Calculator(GetCalculatedValueDelegate del, int x, int y)   
  14. {   
  15.     return del(x, y);   
  16. }   
  17.   
  18. static void Main(string[] args)   
  19. {   
  20.     Console.WriteLine(Calculator(AddCalculator, 10, 20));   
  21. }   

在上面的例子中,Calculator函數的第一個參數就是一個委託。事實上,Calculator對x和y將會作什麼處理,它自己並不知道,如何處理x和y由GetCalculatedValueDelegate來決定。那麼在Main方法裏,咱們將AddCalculator方法做爲參數傳遞給Calculator,表示讓Calculator用AddCalculator的邏輯去處理x和y。這也很形象:Calculator說:「我不知道要怎麼處理x和y,讓del去處理好了!」因而就把x和y扔給了del。對象

這種作法其實跟「模板方法模式」有點點相似。在模板方法模式中,能夠將可變的部分留給子類去重寫,而將不變的部分由父類實現。那麼在委託做爲參數的狀況下,Calculator能夠本身處理不變的邏輯,而將「具體怎麼作」的事情委託給他人去辦理。接口

委託做爲參數,在C#中很是常見。好比線程的建立,須要給一個ThreadStart或者ParameterizedThreadStart委託做爲參數,而在線程執行的時候,將這個參數所指代的函數用做線程執行體。再好比:List<T>類型的Find方法的參數也是一個委託,它把「怎麼去查找」或者說「怎麼樣纔算找到」這個問題留給了開發人員。開發人員只須要定義一個參數爲T,返回值爲布爾型的函數,實現函數體,並將函數做爲參數傳給Find方法,就能夠完成集合中元素的查找。事件

委託做爲返回值通常會用在「根據不一樣狀況決定使用不一樣的委託」這樣的情形下。這有點像工廠模式,不過委託用做返回值仍是用的沒有用做參數這樣頻繁。ip

與委託相關的概念還有不少,好比異步調用、泛型委託、匿名方法、Lambda表達式、事件、協變與逆變等。我會在後續的文章中陸續介紹。

相關文章
相關標籤/搜索