C# 的高级特性2——事件

目录

1,什么是事件

1.1事件的定义

1.2事件和委托的区别

1.3事件模型的5个组成部分

2,怎样使用事件

2.1Talk is cheap, show me the code.

2.2 EventHandler 委托类型,标准事件的用法


1,什么是事件

1.1事件的定义

事件可以被认为是一种发生在对象上的通知,当特定的操作或条件发生时,它会通过委托将控制权传递给事件处理程序。委托是一个引用类型,它可以指向要执行的方法。可以使用+=运算符将委托添加到事件中,使用-=运算符将其从事件中移除。

事件处理程序是由程序员编写的代码块,它们指定了在事件发生时应执行的操作。当事件被触发时,事件处理程序将被调用,从而可以响应事件并执行相应的操作。

例如,一个按钮可以有Click事件。当用户单击该按钮时,Click事件将被触发,并且相关的事件处理程序将被调用。程序员可以编写事件处理程序来执行任何适当的操作,例如打开新窗口、更新数据、保存文件等等。

1.2事件和委托的区别

事件和委托是两种不同的概念。

委托是一种引用类型,它可以指向一个或多个方法,并且可以将委托作为参数或返回值进行传递。委托可以用于实现回调和异步编程等功能。委托是一种非常灵活和强大的机制,它是事件实现的基础。

事件是一种语言特性,是成员,它是基于委托实现的一种机制。事件通常用于响应用户操作、线程信号等等。事件的发布者在某个条件满足之后,会触发事件,然后通知所有订阅者执行相应的操作。事件实际上是一种安全的委托,它只允许订阅者添加或移除委托,但不允许修改委托列表。

因此,委托和事件是相互关联的两种概念。委托提供了一种方法执行的机制,而事件则是委托的一种应用,通过事件机制可以实现对象间的通信和协作。在实际编程中,委托和事件经常会一起使用,尤其是在GUI应用程序中,事件和回调函数是用户交互的基础。

1.3事件模型的5个组成部分

使用事件时的5个源代码组件

  • 委托类型声明    事件和事件处理程序必须有共同的签名和返回类型,它们通过委托类型进行描述
  • 事件处理程序声明    订阅者类中会在事件触发时执行的方法声明。他们不一定是显示命名的方法,还可以是匿名方法或者Lambda表达式
  • 事件声明    发布者类必须声明一个订阅者类可以注册的事件成员。当类声明的事件为public时,称为发布了事件
  • 事件注册    订阅者必须注册事件才能在事件被触发时得到通知。这是将事件处理程序与事件相连的代码
  • 触发事件的代码    发布者类中“触发”事件并导致调用注册的所有事件处理程序的代码

注意:1,任何注册到事件(如注册)的处理程序都必须与委托类型的签名和返回值类型匹配

2,事件是类或结构的成员,不是类型,因此不能使用new表达式来创建它的对象

2,怎样使用事件

2.1Talk is cheap, show me the code.

直接看栗子:

    delegate void Handler();        //声明委托,或者使用已有的委托类型


    //发布者类
    class Incrementer
    {
        public event Handler CountedADozen;    //创建事件并发布

        public void DoCount()
        {
            for (int i = 0; i < 10; i++)
            {
                if (i%3 ==0 && CountedADozen != null)
                {
                    CountedADozen();       //每增加3个计数触发事件一次
                }
            }
        }

    }

    //订阅者类
    class Dozens
    {
        public int DozensCount { get; set; }

        public Dozens(Incrementer incrementer)
        {
            DozensCount = 0;

           //订阅事件(这里是订阅事件的简略通用的写法,订阅事件也可以用Lambda表达式赋值)
            incrementer.CountedADozen += IncrementDozensCount;   
        }

        //声明事件处理程序
        void IncrementDozensCount()
        {
            DozensCount++;
        }

    }

    class Program
    {
        static void Main()
        {
            Incrementer incrementer = new Incrementer();
            Dozens dozensCounter = new Dozens(incrementer);

            incrementer.DoCount();
            Console.WriteLine("Number of dozens = {0}",dozensCounter.DozensCount);
        }
    }

注意:1,事件封装委托,使程序更安全,更有逻辑

2,这里的订阅语句其实是简略后的语法糖衣,在简化后的语法糖下,完全可以当事件是一个委托字段,把它当委托用,虽然这种理解是错的,但是理解使用起来更方便,更容易接受

2.2 EventHandler 委托类型,标准事件的用法

因为事件的广泛使用,.NET框架提供了一个标准模式。该标准模式的基础就是System命名空间中声明的EventHandler委托类型,这是个定义好的专门用于定义事件的通用委托

以下是EventHandler委托类型的声明:

   public delegate void EventHandler(object sender, EventArgs e);

将上面的程序改为使用系统定义的EventHandler委托之后,代码如下:


    //发布者类
    class Incrementer
    {
        public event EventHandler CountedADozen;    //使用EventHandler委托创建事件并发布

        public void DoCount()
        {
            for (int i = 0; i < 10; i++)
            {
                if (i%3 ==0 &&CountedADozen != null)
                {
                    CountedADozen(this,null);       //触发事件时使用EventHandler的参数
                }
            }
        }

    }

    //订阅者类
    class Dozens
    {
        public int DozensCount { get; set; }

        public Dozens(Incrementer incrementer)
        {
            DozensCount = 0;
            incrementer.CountedADozen += IncrementDozensCount;   //订阅事件
        }
        

        //事件处理程序的签名必须与委托的签名匹配
        void IncrementDozensCount(object source,EventArgs e)    
        {
            DozensCount++;
        }

    }

    class Program
    {
        static void Main()
        {
            Incrementer incrementer = new Incrementer();
            Dozens dozensCounter = new Dozens(incrementer);

            incrementer.DoCount();
            Console.WriteLine("Number of dozens = {0}",dozensCounter.DozensCount);
        }
    }

其他:还可以自定义一个派生自EventArgs的类,新自定义类的委托类型,来使得可以向事件处理程序的第二个参数传递数据。

另外,一些刘铁猛老师的课程图片可供参考:

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值