delegate委托對于初學者來說不太好理解。
按筆者的經驗,delegate本質是函數指針,可以把它理解為某一類方法的入口,把他翻譯為:“長得像XXX的函數方法(入參是什么、返回值是什么)”可能更容易理解。
以下示例是delegate的寫法列舉:
//步驟一 聲明委托public delegate string SayHelloDelegate(string name);internal class Program{static void Main(string[] args){//步驟二 初始化/賦值//寫法1SayHelloDelegate sayHello1 = MySayHello;//寫法變種2SayHelloDelegate sayHello2 = delegate (string name) { return "Hello " + name; };//寫法變種3SayHelloDelegate sayHello3 = (string name) => { return "Hello " + name; };//寫法變種4SayHelloDelegate sayHello4 = name => { return "Hello " + name; };//寫法變種5SayHelloDelegate sayHello5 = name => "Hello " + name;//步驟三 調用var msg = sayHello1("foolishsunday");//sayHello2("foolishsunday");//sayHello3("foolishsunday");//sayHello4("foolishsunday");//sayHello5("foolishsunday");Console.WriteLine(msg);//由于delegate的使用每次都需要步驟一聲明委托,因此微軟添加了語法糖Func和Action,把步驟一和二合并在一塊寫//Func示例Func<string, string> funcHello1 = MySayHello;Func<string, string> funcHello2 = (string name) => { return "Hello " + name; };Func<string, string> funcHello3 = name => { return "Hello " + name; };Func<string, string> funcHello4 = name => "Hello " + name;//調用Funcvar result = funcHello1("test");Console.WriteLine(result);Console.ReadLine();}static string MySayHello(string name){return "Hello " + name;}}
輸出:
Hello foolishsunday
Hello test
可見Func的寫法及多種變種寫法都跟delegate如出一轍,但用Func更簡化,而且Func能直觀看到入參和返回值;
在實際編程中,很多情況需要把函數指針作為參數傳入
因為具體函數的實現往往是變化的,但函數入口是不變(這里的函數入口指的是入參與返回值組成的函數形式)
其實delegate/Func/Action并不少見,尤其是C#底層代碼,幾乎隨處可見
舉個常見例子,linq中就大量用到Func
//Where方法的底層定義://其中入參就有Func<TSource, bool> predicatepublic static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
使用Where看看
//例:查找長度為2的字符串并打印//本例中的where方法就是需要傳入一個Func<TSource, bool> predicate作為參數(e => e.Length == 2)"a,bb,ccc".Split(',').Where(e => e.Length == 2).ToList().ForEach(e => Console.WriteLine(e));//而Func<TSource, bool> predicate入參也可以因需求變更為(e => e.StartsWith("c")):查找c開頭的字符串"a,bb,ccc".Split(',').Where(e => e.StartsWith("c")).ToList().ForEach(e => Console.WriteLine(e));Console.ReadLine();
總結:
- delegate有多種寫法,只不過是一個比一個簡化而已。
- 甚至Func/Action的出現都是為了簡化delegate的寫法。
- 它的本質也是一個函數指針,它可以實現函數/方法作為參數傳入另一個函數方法體。
- 在學習設計模式中,我們學過:找到變化并封裝之,把不變的和易變的隔離開來。
委托就很好體現了這種封裝,某一類函數的入參與返回值總是不變的,它的具體實現過程是可變的。我們就可以把它提煉為一個委托。