• .Net之美读书系列(一):委托与事件


    开启新的读书之旅,这次读的书为《.Net之美:.Net关键技术深入解析》。

    我是选择性阅读的,把一些自己觉得容易忘记的,或者比较重要的知识点记录下来,以便以后能方便呢查阅。

    尊重书本原作者,如果大家能有个可能的话,去看看这本书,作者写得挺不错的。例子和知识点各方面都写挺不错的。

    本章的内容

    什么是委托/创建委托类型的写法/事件与委托/发布者和订阅者(观察者模式)

    什么是委托:

    说白了就是平时我们把变量当参数传递的时候,这个变量的类型可以是int类型,double类型,string类型以及各种自定义引用类型等等,但是有时候,我们需要的把一个方法当作参数传入到另外方法中,这个时候就需要一个容器去存储,这个时候该类型的名称就是成为“委托”。

    创建委托类型的写法:

    一个普通的方法名:  public  void NomalMenthod(string parameter)

    一个方法的委托   :  public delegate void MenthodDelegate(string parameter);

    委托与方法有什么不同呢,不同之处就是都了delegate进行修饰,以及不同的名称而已,它们的共同点就是:相同的返回类型,相同的参数。其实,一个委托最终也是编译成一个类。以下标出委托的写法与用法:

            public static void Main(string[] args)
            {
                //使用委托。传入与委托相同类型的方法作参数
                sayhi("猪猪猪扒",ChineseSay);
                Console.Read();
            }
            //1.目的是一个问号的方法,但是各个国家的方式问好方法不相同,在代码层面中需要一个这些方法共同的特点来做一个统一,所以把委托做一个参数
            public static void sayhi(string name, MenthodDelegate delegatemethod)
            {
                delegatemethod(name);
            }
            //2.定义一个委托类型作为统一的方法的类型
            public delegate void MenthodDelegate(string parameter);
    
            //3.1这两步都是说明方法是动作不一样而已。
            public static void ChineseSay(string name)
            {
                Console.WriteLine("李好 " + name);
            }
            //3.2这两步都是说明方法是动作不一样而已。
            public static void EnglishSay(string name)
            {
                Console.WriteLine("Morning " + name);
            }

    创建一个委托(注意不是创建委托类型),为委托绑定方法,一个委托可以有绑定多个方法,委托的调用

            public static void Main(string[] args)
            {
                //创建一个委托(传入参数时已经绑定了一个委托了)
                MenthodDelegate m = new MenthodDelegate(ChineseSay);
                //为委托绑定第二个方法
                m += EnglishSay;
                //委托的调用方式1
                m.Invoke("我是参数");
                //委托的调用方式2
                m("我是参数");
                //为委托取消方法的绑定
                m -= EnglishSay;
    
                Console.Read();
            }

    事件与委托

    事件就是对委托的封装,如果在一个类中,委托声明为privite,则不能暴露到给类外的,但是又不想该委托直接被赋值修改,所以这个时候就定义了事件。

    定义事件的写法:public event MenthodDelegate MenthodEvent;

    事件就类似于定义个委托变量,只是多了public修饰符和event,在该类中外部,如果要访问并注册事件时,只能使用“+=”和“-=”。

    类中的调用调用直接使用 MenthodEvent()或者MenthodEvent.Invoke()就可以了。

        public class DelegateClass
        {
            //在类中封装委托为事件
            public event MenthodDelegate menthodevent;
    
            //调用事件
            public void testdelegate(string name)
            {
                if (menthodevent != null)
                {
                    menthodevent(name);
                }
            }
        }
    
            //在另外一个方法中调用
            public static void Main(string[] args)
            {
                DelegateClass dc = new DelegateClass();
                //注册事件
                dc.menthodevent += EnglishSay;
                dc.testdelegate("我是参数");
    
                Console.Read();
            }    

    发布者和订阅者(观察者模式)

    发布者表示发布事件的代码,就是供订阅者在事件上使用+=来注册事件的一方,通俗一点的意思就是:发布事件的代码;订阅者就是订阅事件的一方,就是使用+=中右边的方法,理解为订阅事件的代码;

    如果没有事件event进行封装,那么在类的外部,创建了类的对象后,可以随意触发事件,对于订阅事件来说是一件极其不利的事件,所以事件更好地实现了发布者和订阅者的模式。

    至今我还是觉得观察者模式和发布者模式一个概念,只是说法上不一样而已,观察者就是订阅事件的人,而被观察者就是发布事件的人.

    Observer设计模式:Observer设计模式是为了定义对象间的一种一对多的依赖关系,以便于当一个对象的状态改变时,其他依赖于它的对象会被自动告知并更新。Observer模式是一种松耦合的模式.

    观察者模式:

            public static void Main(string[] args)
            {
                //被观察者
                Heater heater = new Heater();
                
                //注册事件
                heater.Boiled += (new ConsoleApplication1.Alarm()).MakeAlert;
                heater.Boiled += (new ConsoleApplication1.Display()).ShowMsg;
    
                //就是此触发事件的
                heater.BoilWater();
                Console.Read();
            }
        public class Heater
        {
            public string type = "RealFire 001";
            public string area = "China Xian";
            private int temperture;//水温    
            public delegate void BoiledEventHandler(Object sender, BoiledEventArgs s);
            public event BoiledEventHandler Boiled;
    
           //3.在观察对象想传递它自身属性属性给观察者,这时候就需要另外构建一个参数类型,就是此类型了.
            public class BoiledEventArgs : EventArgs
            {
                public readonly int temperature;
                public BoiledEventArgs(int temperature)
                {
                    this.temperature = temperature;
                }
            }
    
            //2.这里是执行触发的事件操作的代码
            protected virtual void OnBoiled(BoiledEventArgs e)
            {
                if (Boiled != null)
                {
                    Boiled(this, e);
                }
            }
    
            //1.此方法是被观察对象的触发事件的代码,在什么情况下触发事件由此方法决定
            public virtual void BoilWater()
            {
                for (int i = 0; i < 100; i++)
                {
                    temperture = i;
                    if (temperture > 95)
                    {
                        //构造参数-->分别为第3步
                        BoiledEventArgs args = new BoiledEventArgs(temperture);
                        //调用操作委托的方法--->第2步
                        OnBoiled(args);
                    }
                }
            }
        }
    
        //观察者1
        public class Alarm
        {
            /// <summary>
            /// 观察者需要执行的方法的参数由观察对象提供
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            public void MakeAlert(Object sender,Heater.BoiledEventArgs e)
            {
                Console.WriteLine("现在" + e.temperature + "");
            }
        }
    
        //观察者2
        public class Display
        {
    
            /// <summary>
            /// 观察者所需要做的操作
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e">类型由观察对象提供,参数对象只需要获取可以了</param>
            public void ShowMsg(Object sender, Heater.BoiledEventArgs e)
            {
                Console.WriteLine(" Display: 水快开了, 当前温度:{0} 度。", e.temperature);
            }
        }

    以上就是观察者模式以及一些自我的了解,.net自带的委托写法也是按照以上的格式.其中一些规范如下:

    • 委托类型的名称都应该以EventHandler结束。
    • 委托的原型定义有一个void返回值,并接受两个输入参数:一个Object类型,一个EventArgs类型( 或继承自 EventArgs)
    • 事件的命名为委托去掉EventHandler之后剩余的部分。
    • 传入事件的参数的应该继承自EventArgs,并且以此结尾.

    我是把委托简单理解为4种操作。

    1.创建委托类型
    2.创建委托变量(封装了就叫事件)
    3.为委托变量注册方法
    4.委托的调用
    5.直接把方法当作参数使用

  • 相关阅读:
    国内固定电话正则验证:'tel': [/0d{2,3}-d{7,8}(|([-u8f6c]{1}d{1,5}))$/, "请填写有效的电话号码"],
    戴尔3542安装ubuntu时出现:failed to lead ldlinux.c32
    解决:IntelliJ IDEA 编译错误,提示 Compilation failed: internal java compiler error
    超详细~Windows下PyCharm配置Anaconda环境教程!!
    python数据可视化--matplotlib用户手册入门:pyplot画图
    python数据分析——numpy创建多维数组的方式
    python timeit 模块使用,解决%timeit无法使用
    MySQL导入导出数据的中文乱码问题
    如果启动mysql时候,报第一行错误,基本是这个原因没跑了
    mysql安装后服务启动不了(总结)
  • 原文地址:https://www.cnblogs.com/zhuzhuzhupa/p/5244579.html
Copyright © 2020-2023  润新知