C#扫盲篇(三):Action和Func委托–实话实说

一、 基础定义

老王想找老张的老婆出去耍,但是一看,老张还在厨房煮饭。于是老王就对老张隔壁的淑芬说:“等下老张吃完饭出去喝茶,你就把前门晒的苞谷收了,老张从左门出,你就收右边的苞谷,我就知道从鸡舍进来。老张从右门出,你就收左墙的苞谷,我就从侧屋翻墙进来”。

在这个过程中,

  • 事件就是:”老张吃完饭去喝茶“
  • 委托就是:“把前门的苞谷收了”
  • 回调函数就是:“找老张的老婆去耍”
  • sender就是:老张
  • 事件句柄就是: 淑芬
  • EventArgs就是事件参数 : 收左边的苞谷还是右边的苞谷

1.声明格式:

——用关键字“ delegate ”修饰委托      

—— 委托的返回类型和参数要和被委托的方法保持一致 例如:

public class TestClass
    {
        public delegate int delegateAction();
        public event delegateAction OnActionEvent;
        public delegateAction daNew;
    }

2.委托和方法关联

在声明了委托和定义好方法之后,我们需要将委托和方法进行关联,这样委托才能知道自己要调用的是哪个方法。

//委托和方法关联
MyDelegate my = new MyDelegate(MyClass.Method1);

3. 委托调用方法

将委托和方法进行关联之后,我们就可以直接操作委托实例来进行方法的调用,调用方式和直接调用方法差不多。

 //实例化委托的实例方法
 MyClass c = new MyClass();
 My my2 = new My(c.Methods);
 my("Hello");
 my2("Hello");

4. 效果

有了上面的使用之后,我们会发现委托基本都是根据具体方法来声明的,如果不同的方法有3个,4个或者更多的参数,显然,我们需要分别声明不同参数个数的委托,不经意间多了一道“声明委托”的门槛。于是,在.Net Framework3.5版本之后发布了.Net自带的内置委托Action和Func。我们不用再做“声明委托”的工作,直接可以使用。

5.Action委托

Action委托提供无参数、有参数方法,但不提供返回类型,具有Action、Action、Action、Action……Action多达16个参数的形式,其中传入参数均采用泛型T,涵盖了几乎所有可能存在的无返回值的委托类型。

6.Func委托

Func委托提供无参数、有参数方法,同时提供返回类型,具有Func、Func……Func17种类型重载,T1……T16为参数,Tresult为返回类型。

前面我们说,Action委托和Func委托不用再声明,便可直接使用,除了这一点,它们还支持匿名函数、lamda表达式形式。

7.Action委托 与Func委托区别

看出Func与Action是类似的,唯一的区别就是,Func必须指定返回值的类型,使用方式与委托咱们自己使用委托变量是一样的,直接使用相应参数的Func或者Action声明变量,=或者+=挂载函数(方法即可)

这两个其实说白了就是系统定义好的Delegate,他有很多重载的方法,便于各种应用情况下的调用。他在系统的System命名空间下,因此全局可见。

二、 匿名函数

如果你没有晕的话,再来看一下匿名委托,其实这也是一种偷懒的小伎俩而已

看代码说话:

//F = new Func(HelloWorld1);

其实也可以简写成这样:

F = HelloWorld1;          

//F2 = new Func(HelloWorld2);

其实也可以简写成这样

F2 = HelloWorld2;

方法直接赋值给委托,这二个类型不同吧???

没错,你会发现编译一样能通过,系统在编译时在背后自动帮我们加上了类似 “= new Func”的东东,所以我们能偷懒一下下,这个就是匿名委托。

如果你细心的话,会发现我们在定义Button的Click处理事件时,通常是这样的:

this.button1.Click += new EventHandler(button1_Click);

但有时候我们也可以写成这样:

this.button1.Click += button1_Click;

这其实就是匿名委托的应用. 

三、lamda表达式

//使用lambda 表达式
     NoParameter noParameterNew1 = new NoParameter(
          () => Console.WriteLine("我是:无参无返回值方法")
     );

     Parameter parameterNew1 = new Parameter(
           (Para) => Para  
    );

四、Action委托实例

Action委托和Func委托的唯一区别就是没有返回类型,其他用法都一样,当不需要返回类型的时候,直接用Action委托。 class Program

    {
        static void Main(string[] args)
        {
            string mid = ",mid";
            Action anonDel = delegate (string param)
            {
                param += mid;
                param += " and this.";
                Console.WriteLine(param);
            };

            anonDel += delegate (string t)
            {
                Console.WriteLine(t + System.Guid.NewGuid().ToString());
            };

            anonDel("www.webczw.com");

            Console.ReadKey();
        }
    }

多学两招: 委托的使用场景示例

(1)服务器对象可以提供一个方法,客户端对象调用该方法为特定的事件注册回调方法。当事件发生时,服务器就会调用该回调函数。通常客户端对象实例化引用回调函数的委托,并将该委托对象作为参数传递。

(2)当一个窗体中的数据变化时,与其关联的另外一个窗体中相应数据需要实时改变,可以使用委托对象调用第二个窗体中的相关方法实现。

五、总结

为了实现方法的参数化,提出了委托的概念,委托是一种引用方法的类型,即委托是方法的引用,一旦为委托分配了方法,委托将与该方法具有完全相同的行为。大家在看的同时一定也要动手实践,这样才能把知识变成自己的体系。希望能给一些朋友捋捋思绪,形成自己的知识体系。

往期精彩:

首发自:【程序员不帅哥 】公众号

原文链接:https://mp.weixin.qq.com/s/LCPLjBmmbJwXBDWdi3SU1g

扫码关注,更多精彩内容及时获取,一起提高,一起加油