c#编码技巧(十四):全面总结delegate、Func委托的写法演变

delegate委托对于初学者来说不太好理解。
按笔者的经验,delegate本质是函数指针,可以把它理解为某一类方法的入口,把他翻译为:“长得像XXX的函数方法(入参是什么、返回值是什么)”可能更容易理解。
以下示例是delegate的写法列举:

    //步骤一 声明委托
    public delegate string SayHelloDelegate(string name);
    internal class Program
    {
        static void Main(string[] args)
        {
            //步骤二 初始化/赋值
            //写法1
            SayHelloDelegate sayHello1 = MySayHello;
            //写法变种2
            SayHelloDelegate sayHello2 = delegate (string name) { return "Hello " + name; };
            //写法变种3
            SayHelloDelegate sayHello3 = (string name) => { return "Hello " + name; };
            //写法变种4
            SayHelloDelegate sayHello4 = name => { return "Hello " + name; };
            //写法变种5
            SayHelloDelegate 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;

            //调用Func
            var 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 predicate
            public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)

使用Where看看

            //例:查找长度为2的字符串并打印
            //本例中的where方法就是需要传入一个Func predicate作为参数(e => e.Length == 2)
            "a,bb,ccc".Split(',').Where(e => e.Length == 2).ToList()
                .ForEach(e => Console.WriteLine(e));

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

你可能感兴趣的:(C#,c#,开发语言)