C#-事件的详细用法

发布于:2023-01-21 ⋅ 阅读:(380) ⋅ 点赞:(0)

什么是事件

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

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

事件的处理需要委托实现来调度事件,所以事件和委托是紧密关联的(耦合性高)

通过事件使用委托

事件在类中声明且生成,且通过使用同一个类或其他类中的委托与事件处理程序关联。 包含事件的类用于发布事件。这被称为 发布器(publisher) 类。其他接受该事件的类 被称为 订阅器(subscriber) 类。事件使用 发布-订阅(publisher-subscriber) 模型。

发布器(publisher) 是一个包含事件和委托定义的对象。事件和委托之间的联系也定义 在这个对象中。发布器(publisher)类的对象调用这个事件,并通知其他的对象。

订阅器(subscriber) 是一个接受事件并提供事件处理程序的对象。在发布器(publisher) 类中的委托调用订阅器(subscriber)类中的方法(事件处理程序)。

简单来说就是事件可以为任何一种委托类型提供一种发布/订阅机制。用户可以订阅这 个事件,当发布者触发事件后,所有的订阅者都会收到通知。关键是发布者不知道订阅 者是谁,有多少个订阅者。这样的好处是各个模块可以专心做自己的事,不需要过问其 他模块的事情。

声明事件步骤

在类的内部声明事件,首先必须声明该事件的委托类型。例如:

public delegate void PrintHandler();

其次,使用 event 关键字声明事件本身:

public event PrintHandler printTest;

上面的代码定义了一个名为 PrintHandler的委托和一个名为 PrintTest 的事件,该事件在生成的时候会调用委托。

然后调用事件,但是只能在声明事件的类中调用事件

If(printTest!=null)

    printTest();

或者

printTest?.Invoke();

这个代码就是判断printTest是否为空,不为空就调用printTest()方法,为空就不执行

最后注册事件,这里声明事件的类为Sample类

Sample.printTest+=实例方法/静态方法

取消订阅的话用-=即可

下面用一段代码演示:

using System;


namespace ConsoleApp1
{
    //发布器类
    public class Sample
    {
        //声明委托
        public delegate void OrderEventHandler(int x);
        //声明事件
        public event OrderEventHandler order;
        //调用事件
        protected virtual void OnCall()
        {
            order?.Invoke(99);
        }
        public void Start()
        {
            OnCall();
        }
    }
    //订阅器类-1
    public class SubscribEvent1
    {
        public void Print(int x)
        {
            Console.WriteLine("订阅器1,打印数字:"+x);
        }
    }
    //订阅器类-2
    public class SubscribEvent2
    {
        public void Print(int x)
        {
            Console.WriteLine("订阅器2,打印数字:"+x);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            //实例化对象-订阅器类
            SubscribEvent1 se1 = new SubscribEvent1();
            SubscribEvent2 se2 = new SubscribEvent2();
            //实例化对象-发布器类
            Sample sample = new Sample();
            //订阅
            sample.order += se1.Print;
            sample.order += se2.Print;
            //调用事件
            sample.Start();
            Console.ReadLine();
        }
    }
}

输出结果:

订阅器1,打印数字:99
订阅器2,打印数字:99

上面我们用发布器类的start函数来调用Oncall函数引发一个事件。通常要引发事件, 应该使名称定义受保护的虚拟方法,protected和virtual使派生类能够覆盖引发事件的 逻辑,但是派生类要始终调用这个受保护的方法,以确保注册的委托接收事件

我们+=来订阅事件,这里订阅了两个方法,当调用事件时这两个方法都会调用

内置 EventHandler 委托

系统内置了两个常用的委托类型 EventHandler EventHandler<TEventArgs> 。通常, 任何事件都应包括两个参数:事件源和事件数据。EventHandler 主要用于不包含事件数 据;对包含事件数据的使用 EventHandler<TEventArgs>

如有错漏之处,敬请指正!

本文含有隐藏内容,请 开通VIP 后查看