首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >C#学习笔记 事件

C#学习笔记 事件

作者头像
乐百川
发布2022-05-05 18:47:26
发布2022-05-05 18:47:26
3780
举报

事件为委托提供了一种发布/订阅机制。声明事件的类被称为发行者类,其他类可以订阅发行者类中的事件。当发行者类触发其中的事件时,所有订阅该事件的类都会收到这个变化。在图形界面框架中,这种情况非常常见。

事件发布者

首先需要创建一个事件发布者类。该类包含一个委托,并有一个基于该委托的事件,还应该有一个可以触发事件的函数,以便订阅者可以在其他地方接收到这个事件。事件常常定义为一个包含事件发布者和事件消息传递的委托。

代码语言:javascript
复制
//事件发布者
class NewsPublisher
{
    //定义事件的委托
    public delegate void NewsEventHandler(NewsPublisher sender, NewsEventArgs args);
    //用委托定义的事件
    public event NewsEventHandler NewsEvent;
    //构造函数,初始化一个发布者的名称
    public NewsPublisher(string name)
    {
        Name = name;
    }
    //发布事件的函数
    public void PublishNews(string News)
    {
        //当事件有订阅者的时候
        if (NewsEvent != null)
        {
            NewsEvent(this, new NewsEventArgs(News));
        }
    }
    public string Name { set; get; }
}

事件传递的消息

跟随事件传递的消息类,既可以是一个包含很多信息的复杂类,也可以是一个仅仅包含一个字符串的简单类。在这里简单的定义一个只包含一条字符串信息的类来传递消息。

代码语言:javascript
复制
//定义需要随事件传递的信息
class NewsEventArgs
{
    public NewsEventArgs(string News)
    {
        this.News = News;
    }
    public string News
    {
        get; set;
    }
}

事件订阅者

有了事件发布者和事件消息之后,就可以定义事件订阅者了。订阅者需要有一个和发布者事件匹配的方法,用来接收事件响应。

代码语言:javascript
复制
//订阅事件的类
class NewsReader
{
    //在构造函数中订阅一个事件
    public NewsReader(string name, NewsPublisher publisher)
    {
        Name = name;
        publisher.NewsEvent += HandleNewsEvent;
    }

    public string Name { get; set; }
    //订阅的方法需要和事件类型匹配
    public void HandleNewsEvent(NewsPublisher sender, NewsEventArgs args)
    {
        Console.WriteLine($"{Name} 收到 {sender.Name} 发来的消息:{args.News}");
    }
}

事件的使用

有了事件发布者和事件订阅者,就可以来看看事件是怎么运作的了。

代码语言:javascript
复制
NewsPublisher publisher = new NewsPublisher("新闻发布者");

NewsReader reader1 = new NewsReader("读者1", publisher);
NewsReader reader2 = new NewsReader("读者2", publisher);
NewsReader reader3 = new NewsReader("读者3", publisher);

Console.WriteLine($"{publisher.Name}发布了一则新闻。");
publisher.PublishNews("早间新闻");

Console.WriteLine($"{publisher.Name}发布了一则新闻。");
publisher.PublishNews("晚间新闻");

这段程序的运行结果如下。从结果可以看出,事件其实就是一个多播委托。同样的,事件订阅者收到事件的顺序和它们订阅的顺序不一定相同,所以不要编写依赖于它们之间顺序的代码。

代码语言:javascript
复制
新闻发布者发布了一则新闻。
读者1 收到 新闻发布者 发来的消息:早间新闻
读者2 收到 新闻发布者 发来的消息:早间新闻
读者3 收到 新闻发布者 发来的消息:早间新闻
新闻发布者发布了一则新闻。
读者1 收到 新闻发布者 发来的消息:晚间新闻
读者2 收到 新闻发布者 发来的消息:晚间新闻
读者3 收到 新闻发布者 发来的消息:晚间新闻

预定义的事件

事件非常地常用,因此微软也为我们预定义了一个泛型委托EventHandler。它的形式如下:

代码语言:javascript
复制
public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e) where TEventArgs: EventArgs;

从这个委托的定义可以看出,这里需要的事件消息类需要继承EventArgs。由于这个委托已经定义在System命名空间了,所以不需要再自己手动定义委托了。上面的例子也可以改写一下了。

首先,事件消息类需要继承EventArgs,除此之外不需要做其他的变动。

代码语言:javascript
复制
class NewsEventArgs : EventArgs
{
    public NewsEventArgs(string News)
    {
        this.News = News;
    }
    public string News
    {
        get; set;
    }
}

然后,事件发布者类需要删掉自定义的委托,并把事件类型改为泛型委托EventHandler。

代码语言:javascript
复制
class NewsPublisher
{
    //使用泛型委托EventHandler
    public event EventHandler<NewsEventArgs> NewsEvent;
    //构造函数,初始化一个发布者的名称
    public NewsPublisher(string name)
    {
        Name = name;
    }
    //发布事件的函数
    public void PublishNews(string News)
    {
        //当事件有订阅者的时候
        if (NewsEvent != null)
        {
            NewsEvent(this, new NewsEventArgs(News));
        }
    }
    public string Name { set; get; }
}

事件订阅者里面也要做一些改动,让方法匹配EventHandler的定义。

代码语言:javascript
复制
class NewsReader
{
    //在构造函数中订阅一个事件
    public NewsReader(string name, NewsPublisher publisher)
    {
        Name = name;
        publisher.NewsEvent += HandleNewsEvent;
    }

    public string Name { get; set; }
    //订阅的方法需要和事件类型匹配
    public void HandleNewsEvent(object sender, NewsEventArgs args)
    {
        Console.WriteLine($"{Name} 收到 {((NewsPublisher)sender).Name} 发来的消息:{args.News}");
    }
}

这样,就可以和原来一样的使用事件了。EventHandler非常常用,在Windows图形界面编程里,会经常看到这样的方式。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2015-11-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 事件发布者
  • 事件传递的消息
  • 事件订阅者
  • 事件的使用
  • 预定义的事件
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档