zoukankan      html  css  js  c++  java
  • (C#)中断程序流程,处理事件(委托,事件,Lambda表达式)2/3

    为了简化自定义方法的构建来为委托调用列表增加和删除方法,C#提供了 event 关键字。在编译器处理event关键字的时候,它会自动提供注销方法以及委托类型任何必要的成员变量。这些委托成员变量总是声明为private的。所以不能直接从触发事件的对象来访问成员。

    定义一个事件分两步:

    1. 定义一个委托类型,包含事件触发时要调用的方法。

    2. 通过 C# event 关键字用相关的委托来声明事件。

    创建一个Car类,可以发送CarIsBroken(), OverSpeedAlarm(超速警告)事件。

               // 创建一个委托用于对Car事件的响应处理。
                public delegate void CarEngineHandler(string msg);
    
                // Car类可以发送的事件
                public event CarEngineHandler eCarIsBroken;
                public event CarEngineHandler eOverSpeedAlarm;

    实际上event会扩展为两个隐藏的公共方法,一个带add_前缀,一个带remove_前缀

    例如: OverSpeedAlarm事件产生两个隐藏的方法:add_OverSpeedAlarm(),remove_OverSpeedAlarm().

    监听传入的事件

     C# 事件简化了注册调用者事件处理程序的操作,无需指定自定义辅助方法,调用者仅需使用+=,-=操作符。(操作符在后台触发正确的add_xxx()或remove_xxx()方法)。

    namespace ConsoleApplication1
    {
        class Program
        {
            public class Car
            {
                // 属性
                public string CarName { get; set; }
                public int CurrentSpeed { get; set; }
                public int MaxSpeed { get; set; }
    
                // 成员
                private bool carIsBroken;
    
                // 构造函数
                public Car() { MaxSpeed = 180; }
                public Car(string name, int maxSpd, int curSpd)
                {
                    CarName = name;
                    CurrentSpeed = curSpd;
                    MaxSpeed = maxSpd;
                   //carIsBroken = false; 
                }
    
                // 创建一个委托用于对Car事件的响应处理。
                public delegate void CarEngineHandler(string msg);
    
                // Car类可以发送的事件
                public event CarEngineHandler eCarIsBroken;
                public event CarEngineHandler eOverSpeedAlarm;
    
                public void Accelerate(int delta)
                {
                    // 如果汽车已坏,触发eCarIsBroken事件
                    if (carIsBroken)
                    {
                        if (eCarIsBroken != null)    // 触发事件!
                        {
                            eCarIsBroken("Car is broken,can't drive now!");
                        }
                    }
                    else
                    {
                        CurrentSpeed += delta;
                    }
    
                    // 超速提醒
                    if (20 == MaxSpeed - CurrentSpeed && eCarIsBroken != null)  // 触发事件!
                    {
                        eOverSpeedAlarm("Alarm: Going too fast, drive slowly!");
                    }
    
                    if (CurrentSpeed >= MaxSpeed)
                    {
                        carIsBroken = true;
                    }
                    else
                    {
                        Console.WriteLine("CurrentSpeed = {0}", CurrentSpeed);
                    }
                }
            }
    
            public static void TheCarIsBroken(string msg)
            {
                Console.WriteLine(msg);
            }
    
            public static void TheCarIsOverSpeed(string msg)
            {
                Console.WriteLine(msg);
            }
                    
        
            static void Main(string[] args)
            {
                Car myCar = new Car("Audio Q5", 200, 60); 
    
                // 注册事件处理程序
                //myCar.eOverSpeedAlarm += new Car.CarEngineHandler(TheCarIsOverSpeed);
                myCar.eOverSpeedAlarm += TheCarIsOverSpeed;
                myCar.eCarIsBroken += TheCarIsBroken;
    
                for (int i = 0; i < 12; i++)
                {
                    myCar.Accelerate(20);
                }
    
                Console.ReadLine();
            }
        }
    }

    创建自定义的事件参数


    对Car类可以进行改进,以符合微软推荐的事件模式。即

    • 第一个参数是System.Object. 表示对发送事件的对象,如Car类的引用。
    • 第二个参数是派生自EventArgs(基类)的子类型。表示与该事件相关的信息。

    对于简单的事件来说,我们可以传递一个EventArgs的实例,如果要传递自定义数据,就需要构建一个派生自EventArgs的类。本例中,我们构建一个CarEventArgs的类,用于传递字符串。

            // 利用EventArgs的派生类,来传递数据。
            public class CarEventArgs : EventArgs
            {
                public readonly string msg;
                public CarEventArgs(string message)
                {
                    msg = message;
                }
            }

    并修改委托.(调整入口参数),和修改事件触发。

                            //eCarIsBroken("Car is broken,can't drive now!");
                            eCarIsBroken(this,new CarEventArgs("Car is broken,can't drive now!"));

    全部程序如下:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            public class Car
            {
                // 属性
                public string CarName { get; set; }
                public int CurrentSpeed { get; set; }
                public int MaxSpeed { get; set; }
    
                // 成员
                private bool carIsBroken;
    
                // 构造函数
                public Car() { MaxSpeed = 180; }
                public Car(string name, int maxSpd, int curSpd)
                {
                    CarName = name;
                    CurrentSpeed = curSpd;
                    MaxSpeed = maxSpd;
                   //carIsBroken = false; 
                }
    
                // 创建一个委托用于对Car事件的响应处理。
                //public delegate void CarEngineHandler(string msg);
                public delegate void CarEngineHandler(object sender, CarEventArgs e); 
    
                // Car类可以发送的事件
                public event CarEngineHandler eCarIsBroken;
                public event CarEngineHandler eOverSpeedAlarm;
    
                public void Accelerate(int delta)
                {
                    // 如果汽车已坏,触发eCarIsBroken事件
                    if (carIsBroken)
                    {
                        if (eCarIsBroken != null)    // 触发事件!
                        {
                            //eCarIsBroken("Car is broken,can't drive now!");
                            eCarIsBroken(this,new CarEventArgs("Car is broken,can't drive now!"));
                        }
                    }
                    else
                    {
                        CurrentSpeed += delta;
                    }
    
                    // 超速提醒
                    if (20 == MaxSpeed - CurrentSpeed && eCarIsBroken != null)  // 触发事件!
                    {
                        //eOverSpeedAlarm("Alarm: Going too fast, drive slowly!");
                        eOverSpeedAlarm(this,new CarEventArgs("Alarm: Going too fast, drive slowly!"));
                    }
    
                    if (CurrentSpeed >= MaxSpeed)
                    {
                        carIsBroken = true;
                    }
                    else
                    {
                        Console.WriteLine("CurrentSpeed = {0}", CurrentSpeed);
                    }
                }
            }
    
            // 利用EventArgs的派生类,来传递数据。
            public class CarEventArgs : EventArgs
            {
                public readonly string msg;
                public CarEventArgs(string message)
                {
                    msg = message;
                }
            }
    
            public static void TheCarIsBroken(object sender, CarEventArgs e)
            {
                Console.WriteLine("{0}:{1}",sender, e.msg);
            }
    
            public static void TheCarIsOverSpeed(object sender, CarEventArgs e)
            {
                Console.WriteLine("{0}:{1}", sender, e.msg);
            }
    
    
                    
        
            static void Main(string[] args)
            {
                Car myCar = new Car("Audio Q5", 200, 60); 
    
                // 注册事件处理程序
                //myCar.eOverSpeedAlarm += new Car.CarEngineHandler(TheCarIsOverSpeed);
                myCar.eOverSpeedAlarm += TheCarIsOverSpeed;
                myCar.eCarIsBroken += TheCarIsBroken;
    
                for (int i = 0; i < 12; i++)
                {
                    myCar.Accelerate(20);
                }
    
                Console.ReadLine();
            }
        }
    }

    输出:

    CurrentSpeed = 80
    CurrentSpeed = 100
    CurrentSpeed = 120
    CurrentSpeed = 140
    CurrentSpeed = 160
    ConsoleApplication1.Program+Car:Alarm: Going too fast, drive slowl
    CurrentSpeed = 180
    ConsoleApplication1.Program+Car:Car is broken,can't drive now!
    ConsoleApplication1.Program+Car:Car is broken,can't drive now!
    ConsoleApplication1.Program+Car:Car is broken,can't drive now!
    ConsoleApplication1.Program+Car:Car is broken,can't drive now!
    ConsoleApplication1.Program+Car:Car is broken,can't drive now!

    ==============================================

    再继续前一篇软件组的例子。 

    事件中有两个角色,一个是发布者(Publisher),一个是订阅者(Subscriber). 在本例子中显然软件Lead 是发布者,而苦逼员工bill,和steven是订阅者。

    老板发话开喊工作(发布事件),bill和steven由于订阅了老板的命名,在收到后就开始工作了(响应事件)

        // Publisher.
        public class SoftwareLead
        {
            public delegate void assignSoftwareWork();
    
            public event assignSoftwareWork onWork;  
    
            public void DoWork()
            {
                if (onWork != null)
                {
                    Console.WriteLine("Hey buddies, let's start working..."); 
                    onWork(); 
                }; 
            }
        }
        public class SoftwareEngineer
        {
            private string engineerName;
    
            public SoftwareEngineer(string name)
            {
                this.engineerName = name; 
            }
    
            public void UpdateFirmware()
            {
                Console.WriteLine("{0} is updating firmware...", this.engineerName); 
            }
    
            public void FixBugs()
            {
                Console.WriteLine("{0} is fixing bugs...", this.engineerName); 
            }
    
            // Subscriber
            public void ReceiveWork()
            {
                Console.WriteLine("Fk, work again?!");
                this.UpdateFirmware();
                this.FixBugs(); 
            }
        }
            static void Main(string[] args)
            {
                SoftwareLead fred = new SoftwareLead();
                SoftwareEngineer bill = new SoftwareEngineer("Bill"); 
                SoftwareEngineer steven = new SoftwareEngineer("Steven");
    
                fred.onWork += bill.ReceiveWork;
                fred.onWork += steven.ReceiveWork;
                fred.DoWork(); 
            }

    显然,当Fred 开始DoWork的时候, OnWork 事件被触发,同时Bill,Steven两位小弟收到了事件,开始干活。

    输出如下:

    Hey buddies, let's start working...
    Fk, work again?!
    Bill is updating firmware...
    Bill is fixing bugs...
    Fk, work again?!
    Steven is updating firmware...
    Steven is fixing bugs...
  • 相关阅读:
    为什么面试要问 hashmap 的原理
    SpringMVC 学习-上传文件分解器 CommonsMultipartResolver 类
    SpringMVC 学习-异常处理 SimpleMappingExceptionResolver 类
    js onblur 和 onkeyup 事件用法
    IntelliJ IDEA “Finds duplicated code”提示如何关闭
    使用 Git 报错 error: src refspec master matches more than one.
    消息队列 RabbitMQ 与 Spring 整合使用
    使用 JUnit 报错 java.lang.Exception: No runnable methods
    MyBatis 学习-与 Spring 集成篇
    MyBatis 学习
  • 原文地址:https://www.cnblogs.com/fdyang/p/2909819.html
Copyright © 2011-2022 走看看