C#基础-事件 Event

事件(Event) 基本上说是一个用户操作,如按键、点击、鼠标移动等等,或者是一些提示信息,如系统生成的通知。应用程序需要在事件发生时响应事件。例如,中断。

C# 中使用事件机制实现线程间的通信。

1.事件的定义

给事件下个准确的定义是一个较困难的事,这里我暂且给它定义为:事件是两个对象之间的交互行为,这里关注四个字“两个对象”。不理解不要紧,这样定义本身并不准确。,继续往下看。

事件定义之前先声明一个委托,然后声明一个事件:

2.事件的三要素

学会运用事件,一定要知道事件的三要素:事件拥有者、事件订阅者、事件处理方法。

事件拥有者:也叫事件发布者,个人觉得用拥有者更方便理解,很显然,谁定义事件谁就是事件的拥有者。具体到代码中也就是哪个类中定义了的事件,那么这个类的实例就是事件的拥有者。

事件订阅者:可理解为“盯着”事件拥有者的某个行为的对象。

事件处理方法:事件触发后要执行的方法。当事件订阅者“发现”事件拥有者的事件被触发时,事件订阅者需要去执行的方法。仔细口味这句话,不难发现事件处理方法是定义在事件订阅者中,后面的代码会体现出来。

事件在类中声明且生成,且通过使用同一个类或其他类中的委托 来关联到 事件处理程序。事件使用 发布-订阅(publisher-subscriber) 模型。

包含事件的类用于发布事件。这被称为 发布器(publisher) 类。

其他接受该事件的类被称为 订阅器(subscriber) 类。

发布器(publisher) 是一个包含事件委托定义的对象。事件和委托之间的联系也定义在这个对象中。

发布器(publisher)类的对象调用这个事件,并通知其他的对象。

订阅器(subscriber) 是一个接受事件并提供事件处理程序的对象。

在发布器(publisher)类中的委托调用订阅器(subscriber)类中的方法(事件处理程序)。

事件和委托的联系与区别

从事件的声明,我们可以大致看出事件与委托的关系,事件是委托的特殊实现,事件是建立在对委托的语言支持之上的。

委托是一种类型,事件是委托类型的一个实例,加上了event的权限控制,限制权限,只允许在事件声明类里面去invoke和赋值,不允许外面,甚至子类调用。

 

用一个简单的例子,来说明一下这种消息传递的机制。
有一家三口,妈妈负责做饭,爸爸和孩子负责吃。。。将这三个人,想象成三个类。
妈妈有一个方法,叫做“做饭”。有一个事件,叫做“开饭”。做完饭后,调用开发事件,发布开饭消息。
爸爸和孩子分别有一个方法,叫做“吃饭”。
将爸爸和孩子的“吃饭”方法,注册到妈妈的“开饭”事件。也就是,订阅妈妈的开饭消息。让妈妈做完饭开饭时,发布吃饭消息时,告诉爸爸和孩子一声。

这种机制就是C#中的,订阅发布。下面我们用代码实现:

class Program
    {
        public static void Main(string[] args)
        {
            //实例化对象
            Mom mom = new Mom();
            Dad dad = new Dad();
            Child child = new Child();
             
            //将爸爸和孩子的Eat方法注册到妈妈的Eat事件
            //订阅妈妈开饭的消息
            mom.Eat += dad.Eat;
            mom.Eat += child.Eat;
             
            //调用妈妈的Cook事件
            mom.Cook();
             
            Console.Write("Press any key to continue . . . ");
            Console.ReadKey(true);
        }
    }
     
    public class Mom
    {
        //定义Eat事件,用于发布吃饭消息
        public event Action Eat;
         
        public void Cook()
        {
            Console.WriteLine("妈妈 : 饭好了");
            //饭好了,发布吃饭消息
            Eat?.Invoke();
        }
    }
     
    public class Dad
    {
        public void Eat()
        {
            //爸爸去吃饭
            Console.WriteLine("爸爸 : 吃饭了。");
        }
    }
     
    public class Child
    {
        public void Eat()
        {
            //熊孩子LOL呢,打完再吃
            Console.WriteLine("孩子 : 打完这局再吃。");
        }
    }

//猫 叫一声   触发一系列后续动作  
        //多了个 指定动作  正是这个不稳定   封装出去   甩锅
         public event Action CatMiaoActionHandler;
         public void MiaoEvent()
        {
            Console.WriteLine("{0} MiaoEvent", this.GetType().Name);
            this.CatMiaoActionHandler?.Invoke();
            Console.WriteLine("*&^&*^*^*(^&*^&*^&*^&*^");
        }

CatMiaoActionHandler

Cat cat = new Cat();
                    
                    cat.CatMiaoActionHandler += new Dog().Wang;
                    cat.CatMiaoActionHandler += new Mouse().Run;
                    cat.CatMiaoActionHandler += new Baby().Cry;

                    //cat.CatMiaoActionHandler.Invoke();
                    //cat.CatMiaoActionHandler = null;

                    cat.CatMiaoActionHandler += new Mother().Wispher;
                    cat.CatMiaoActionHandler += new Brother().Turn;
                    cat.CatMiaoActionHandler += new Father().Roar;
                    cat.CatMiaoActionHandler += new Neighbor().Awake;
                    cat.CatMiaoActionHandler += new Stealer().Hide;
                    cat.MiaoEvent();

cat.MiaoEvent();

事件主要使用三个类:

1. 参数定义类testEventArgs:继承自EventArgs(虽然EventArgs什么也不做)

2. 事件发布类monitor (发布器publisher)

3. 事件侦听类Receiver (订阅器 subscriiber)

using System;
using System.Collections.Generic;
using System.Text;
 
namespace EventLearn
{
    class testArgs:EventArgs
    {
        public string msg;
        public testArgs(string msg)
        {
            this.msg = msg;
        }
    }
 
    class monitor
    {
        public delegate void delegateHander(object sender, testArgs e);
 
        public event delegateHander pressKey;
 
        public void Run()
        {
            do
            {
                Console.WriteLine("Please press any key. Input 'exit' to finish the process!");
                string input=Console.ReadLine();
                if (input == "exit")
                    break;
                pressKey(this,new testArgs(input));
            }
            while(true);
        }
    }
 
 
 
    class Receiver
    {
    public Receiver(monitor Monitor)
    {
        Monitor.pressKey += new monitor.delegateHander(this.process);
    }
 
        public void process(object sender, testArgs e)
        {
            Console.WriteLine("You have input the string: {0}", e.msg);
        }
    }
}

下面是主程序:

using System;
using System.Collections.Generic;
using System.Text;
 
namespace EventLearn
{
    class Program
    {
        static void Main(string[] args)
        {
            monitor Monitor = new monitor();
            Receiver receiver = new Receiver(Monitor);
            Monitor.Run();
            Console.ReadKey();
        }
    }
}

发布了85 篇原创文章 · 获赞 30 · 访问量 27万+

猜你喜欢

转载自blog.csdn.net/qq_42672770/article/details/104436524