zoukankan      html  css  js  c++  java
  • C#委托与事件学习笔记

    委托事件学习笔记

    本文是学习委托和事件的笔记,水平有限,如有错漏之处,还望大神不吝赐教。

    1. 什么是委托?从字面意思来解释,就是把一个动作交给别人去执行。在实际开发中最常用的就是使一个方法可以当做一个参数传递,以便在方法中可以根据实际情况实现不同的功能。
    2. 什么是事件?事件就是发生的事情,例如点击了一下鼠标,对应鼠标单击事件,双击速表对应鼠标双击事件……进行Winform开发的时候就能了解到很多的事件,可以说只有想不到的事件,没有微软不能提供的事件。实际上事件是一种特殊的委托,定义一个事件的时候也需要指定事件所依赖的委托。

    如何声明一个委托呢?

    声明委托需要使用关键字delegate其他与声明一个方法相同,需要指定委托使用的参数和返回值,但是委托的声明是没有具体实现的,委托的实现是在初始化的时候指定委托的方法。

    //声明一个委托,返回值为空,需要两个参数

        //委托的声明与方法类似,所以内部的方法也必须是与委托声明包含相同的传入参数和返回值

    public delegate void CustomDelegate(object sender, CustomArgs args);

    实现自定义的参数类,Winform开发里面可以经常看到EventArgs这个类,他是与触发的事件相关的参数

      //此对象继承自EventArgs用于传递给委托的参数

        //不是强制要求如此声明,只是根据默认约定,实际项目中可根据需要进行声明

        public class CustomArgs : EventArgs

        {

            public string Name { get; set; }

    }

    下面的类是委托和事件使用的公共类

    //用于委托学习的公共类

        public class CustomCommon

        {

            //声明一个事件

            //事件是一种特殊的委托,除了不用指定一个初始的方法之外,使用方法与委托相似

            //事件只能通过+=和-=的方式添加需要执行的方法

            //委托只能在声明它的类内部触发

            public event CustomDelegate CustomHandler;

            public void ShowName(object sender, CustomArgs args)

            {

                Console.WriteLine($"Your name is :{args.Name}");

            }

            public void ShowOther(object sender, CustomArgs args)

            {

                Console.WriteLine("此方法是ShowOther");

            }

            //定义此方法用于触发事件

            public void OnHandler(object sender,CustomArgs args)

            {

                if (CustomHandler != null)//判断事件是否为空

                {

                    CustomHandler(sender, args);

                }

    }

    委托的初始化即调用

                //委托初始化的时候需要传入一个方法

                //委托就是把方法交给别人去执行,所以一定需要在添加了方法之后委托才能执行.所以,必须在初始化的时候添加第一个方法

                CustomCommon common = new CustomCommon();

                CustomArgs cargs = new CustomArgs() { Name = "此坑已满" };

                CustomDelegate handler = new CustomDelegate(common.ShowName);//此处传入的是方法的声明,而不是方法执行的结果

                //handler(null,cargs);//委托的调用与方法的调用相同

    委托内部可以同时添加多个相同声明的方法,称为委托链

    //委托链调用

                //委托可以通过+=和-=添加和移除方法

                //相同对象的同一个方法只能添加一次

                //委托链的执行时按照添加方法的顺序进行执行,如果委托返回值不是void那么委托链的返回值就是最后一个方法执行后的返回值,其他方法的返回值全部都会被舍弃

                handler += common.ShowOther;

                //调用此委托链

                //委托链调用传入的参数,会传递给内部的所有方法,且每个方法获取到的参数一模一样

                //handler(null, cargs);

    事件的使用

    //测试事件

                //事件在Winform程序中使用的非常多,例如按钮的Click事件,Winform的窗体类都是分部类

                //查看Designer类就可以看到CLick+=为事件添加一个处理方法

                common.CustomHandler += ShowMethod;

                //common.OnHandler(null, null);

    //匿名方法

                //匿名方法,即不指定方法的名称,使用delegate关键字代替即可,使用匿名方法可以不用为实现委托而专门去定义一个方法,只需要实现方法即可

                Action<int> action = new Action<int>(delegate (int value) { Console.WriteLine($"This Value is {value}"); });

                //action(10);

     

                //Lambda表达式

                //Lambda更加简化了委托的编程只需要=>即可实现方法

                //Lambda使用格式,(x,y)=>{dosomthing}

                //如果只有一个参数那么可以写为 x=>{dosomthidng}

                //如果只有一句代码,那么可以写为x=>dosomthing

                //如果没有参数,那么就不能省略()必须写为()=>{dosomthing}

                //x,y是参数的表示符,C#编译器会自动推测其类型,而其值即为调用委托时传入的值

                //如下t的类型为int其值为10

                Action<int> actionL = (t) => { Console.WriteLine($"This is a Method for Test Lambda value is {t}"); };

                actionL(10);

                   

                Console.ReadKey();

    //下面是事件使用的方法

    public static void ShowMethod(object sender, CustomArgs args)

            {

                Console.WriteLine("This is a Method for Test Event");

            }

    将方法当做一个参数传递

    /// <summary>

            /// 测试委托作为参数传递的方法

            /// </summary>

            /// <param name="list"></param>

            /// <param name="func"></param>

            public int ParaDeleTest(List<int> list, Func<List<int>, int> func)

            {

                if (list != null && list.Count > 0)//判断数组必须包含值,仅为了测试代码简单而实现,实际项目请根据需要进行设置

                {

                    return func(list);//对数据进行操作

                }

                else

                {

                    return -1;

                }

            }

    List<int> list = new List<int>{ 1, 4, 23, 124, 54 };

                //将委托作为参数传入,可以实现在不同的需求情况下,实现不同的功能

                int ave = common.ParaDeleTest(list, (x) => { return (int)x.Average(); });//计算List的平均值

                int max = common.ParaDeleTest(list, x => x.Max());//计算List中的最大值

                Console.WriteLine($"This List Average is {ave},Max is {max}");

  • 相关阅读:
    Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'.
    Qt 下快速读写Excel指南(尘中远)
    QT 那些事
    安卓环境下,通过QT调用jar包
    android使用C/C++调用SO库
    雷军曾定下目标,2017年将聚焦5大核心战略,分别是:黑科技、新零售、国际化、人工智能和互联网金融五大部分
    Maven和Gradle
    链接生成接口
    孤儿进程和僵尸进程
    Case when 的使用方法
  • 原文地址:https://www.cnblogs.com/ckym/p/9821963.html
Copyright © 2011-2022 走看看