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的写法。
- 它的本质也是一个函数指针,它可以实现函数/方法作为参数传入另一个函数方法体。
- 在学习设计模式中,我们学过:找到变化并封装之,把不变的和易变的隔离开来。
委托就很好体现了这种封装,某一类函数的入参与返回值总是不变的,它的具体实现过程是可变的。我们就可以把它提炼为一个委托。