• 委托与事件


    明天还要上班,可我这会儿,总想着写篇博文,要不感觉就像丢了件东西似的,睡不着。成全我自己吧。

    刚走入工作的我,为了更好的工作,我就让自己回炉一次,更深入的理解各个知识点。

    今晚就从委托与事件开始。。

    1.什么是委托。

    委托是一种数据结构,能够引用静态方法或引用实例及其实例方法,他是完全面向对象的,同时也封装了对象实例和方法。委托实例封

    装了一个调用列表,该列表包含了一个会多个方法,每个方法称为一个可调用实体。

    2.我用代码展示委托使用的全过程。(看从1-->5的顺序)

    复制代码
        //1.委托的声明,delegate为声明委托的关键字;
        //public为修饰符,还可以有的修饰符为 protected、internal、private、new
        //new修饰符,只能在其他类型中声明委托时使用,他表示所标明的委托会隐藏具有相同名称的继承成员
       public delegate void D(int i, int j);
       public  class Program
        {
            static void Main(string[] args)
            {
                //3.委托实例化可以创建委托类型的实例,并向该实例注册方法列表
                //委托类型的实例方法列表可以为静态方法,实例方法,或者另外一个委托实例。
                D d1 = new D(U.F1);
                D d2 = new D(U.F2);
                D d3 = d1 + d2;        //这样表示d3实例依次调用U类的F1、F2方法
                D d4 = d3 - d1;       //表示从d3实例的方法列表末端查找,如果该方法包括d1,则移除
    
                //5.委托的调用
              d1(200, 100);   //输出为300
              d2(200, 100);   //100
              d3(50, 10);     //60 40  这里由于实例方法列表中有2个方法,也就调用执行了2个方法,故导出2个值
              d4(70, 40);     // 30
              Console.ReadKey();
            }        
        }
       public class U
        {
            //2.创建向委托注册的方法
            //如果一个方法能够注册到某一个委托中,那么该方法的签名必须与该委托所指定的签名完全匹配
            //匹配规则有2:返回类型必须相同;方法参数必须相同。
    
            public static void F1(int a, int b)
            {
                
                Console.WriteLine((a+b).ToString());
            }
            public static void F2(int w, int j)
            {
                Console.WriteLine((w-j).ToString());
            }
        }
    复制代码

    3. 委托的你深入应用

    复制代码
     public delegate void helloWorld(string name);  //声明委托
        class Program
        {
            static void Main(string[] args)
            {
               //最初的委托
                helloWorld ffdelegate = new Program().ff;  //这里可以直接写入方法。
                ffdelegate("最初最简单的,");
    
                //使用匿名方法。。
                helloWorld sedelegate = delegate(string name) { Console.WriteLine(name+",你好!"); };
                sedelegate("匿名方法");           
    
                //使用拉姆达表达式
                helloWorld thdelegate = (p => { Console.WriteLine(p+",你好"); });
                thdelegate("拉姆达表达式");
    
                //使用Action
                Action<string> fordelegate=(p=>{Console.WriteLine(p+",你好!");});
                fordelegate("Action");
    
                //使用Func
                Func<string, string> fidelegate = (p => p + ",你好!");
                string sayHello = fidelegate("Func");
                Console.WriteLine(sayHello);
    
                Console.ReadKey();
    
            }
    
            public void ff(string name)
            {
                Console.WriteLine(name+"你好!");
            }
        }
    复制代码

    4.事件的使用

    事件是一种使对象或类能够提供通知的成员,其实也是一种特殊类型的委托。他包含两个参数:指示事件源的“对象源”参数和封装事件的其他任何相关信息的e参数。其中,e参数的类型为system.EventArgs类型或从这类型中派生的类型。

     1.事件的简单认识

    复制代码
    namespace 事件
    {
        public delegate void GreetingDelegate(string name); //声明委托
        class Program
        {
            private static void ChineseGreeting(string name)  //定义事件处理程序
            {
                Console.WriteLine("你好, " + name);
            }
    
            static void Main(string[] args)
            {
                GreetingManager gm = new GreetingManager();
                gm.MakeGreet += ChineseGreeting;        //订阅事件(将事件处理程序添加到事件的调用列表中)
                gm.GreetPeople("事件!");
                Console.ReadKey();
            }
        }
        public class GreetingManager
        {
    
            public event GreetingDelegate MakeGreet;  //声明一个事件,event为声明事件的关键字,其实事件是一种特殊类型的委托
            public void GreetPeople(string name)
            {
                MakeGreet(name);                 //把这里的事件看做一个委托来理解,更容易点。
            }
        }
    }
    复制代码

    2.事件的应用 (Observer设计模式--热水器)

    复制代码
    using System;
    using System.Collections.Generic;
    using System.Text;
    
    namespace Delegate {
        // 热水器
        public class Heater {
           private int temperature;
           public string type = "RealFire 001";       // 添加型号作为演示
           public string area = "China Xian";         // 添加产地作为演示
           //声明委托
           public delegate void BoiledEventHandler(Object sender, BoiledEventArgs e);
           public event BoiledEventHandler Boiled; //声明事件
    
           // 定义BoiledEventArgs类,传递给Observer所感兴趣的信息
           public class BoiledEventArgs : EventArgs {
               public readonly int temperature;
               public BoiledEventArgs(int temperature) {
                  this.temperature = temperature;
               }
           }
    
           // 可以供继承自 Heater 的类重写,以便继承类拒绝其他对象对它的监视
           protected virtual void OnBoiled(BoiledEventArgs e) {
               if (Boiled != null) { // 如果有对象注册
                  Boiled(this, e);  // 调用所有注册对象的方法
               }
           }
           
           // 烧水。
           public void BoilWater() {
               for (int i = 0; i <= 100; i++) {
                  temperature = i;
                  if (temperature > 95) {
                      //建立BoiledEventArgs 对象。
                      BoiledEventArgs e = new BoiledEventArgs(temperature);
                      OnBoiled(e);  // 调用 OnBolied方法
                  }
               }
           }
        }
    
        // 警报器
        public class Alarm {
           public void MakeAlert(Object sender, Heater.BoiledEventArgs e) {
               Heater heater = (Heater)sender;     //这里是不是很熟悉呢?
               //访问 sender 中的公共字段
               Console.WriteLine("Alarm:{0} - {1}: ", heater.area, heater.type);
               Console.WriteLine("Alarm: 嘀嘀嘀,水已经 {0} 度了:", e.temperature);
               Console.WriteLine();
           }
        }
    
        // 显示器
        public class Display {
           public static void ShowMsg(Object sender, Heater.BoiledEventArgs e) {   //静态方法
               Heater heater = (Heater)sender;
               Console.WriteLine("Display:{0} - {1}: ", heater.area, heater.type);
               Console.WriteLine("Display:水快烧开了,当前温度:{0}度。", e.temperature);
               Console.WriteLine();
           }
        }
    
        class Program {
           static void Main() {
               Heater heater = new Heater();
               Alarm alarm = new Alarm();
    
               heater.Boiled += alarm.MakeAlert;   //注册方法
               heater.Boiled += (new Alarm()).MakeAlert;      //给匿名对象注册方法
               heater.Boiled += new Heater.BoiledEventHandler(alarm.MakeAlert);    //也可以这么注册
               heater.Boiled += Display.ShowMsg;       //注册静态方法
    
               heater.BoilWater();   //烧水,会自动调用注册过对象的方法
           }
        }
    }
    
    输出为:
    Alarm:China Xian - RealFire 001:
    Alarm: 嘀嘀嘀,水已经 96 度了:
    Alarm:China Xian - RealFire 001:
    Alarm: 嘀嘀嘀,水已经 96 度了:
    Alarm:China Xian - RealFire 001:
    Alarm: 嘀嘀嘀,水已经 96 度了:
    Display:China Xian - RealFire 001:
    Display:水快烧开了,当前温度:96度。
    // 省略 ...
  • 相关阅读:
    HttpRunner3.X
    基于C++的ByteBuf封装
    关于matlab的配色
    关于样本方差的无偏估计
    使用Python求解Nonogram
    菜鸡的一些力扣记录
    LeetCode链表练习
    C语言中的链表
    Python中的链表简介
    Nebula Graph 源码解读系列 | Vol.03 Planner 的实现
  • 原文地址:https://www.cnblogs.com/tangshiguang/p/6741158.html
Copyright © 2020-2023  润新知